aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser')
-rw-r--r--crates/ra_parser/src/grammar.rs12
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs2
-rw-r--r--crates/ra_parser/src/grammar/items.rs93
-rw-r--r--crates/ra_parser/src/grammar/items/consts.rs11
-rw-r--r--crates/ra_parser/src/grammar/items/nominal.rs11
-rw-r--r--crates/ra_parser/src/grammar/items/use_item.rs3
6 files changed, 61 insertions, 71 deletions
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index c9941fe93..e428faffb 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -86,7 +86,7 @@ impl BlockLike {
86 } 86 }
87} 87}
88 88
89fn opt_visibility(p: &mut Parser) { 89fn opt_visibility(p: &mut Parser) -> bool {
90 match p.current() { 90 match p.current() {
91 PUB_KW => { 91 PUB_KW => {
92 let m = p.start(); 92 let m = p.start();
@@ -116,13 +116,19 @@ fn opt_visibility(p: &mut Parser) {
116 } 116 }
117 // test crate_keyword_vis 117 // test crate_keyword_vis
118 // crate fn main() { } 118 // crate fn main() { }
119 CRATE_KW => { 119 // struct S { crate field: u32 }
120 // struct T(crate u32);
121 //
122 // test crate_keyword_path
123 // fn foo() { crate::foo(); }
124 CRATE_KW if p.nth(1) != COLONCOLON => {
120 let m = p.start(); 125 let m = p.start();
121 p.bump(); 126 p.bump();
122 m.complete(p, VISIBILITY); 127 m.complete(p, VISIBILITY);
123 } 128 }
124 _ => (), 129 _ => return false,
125 } 130 }
131 true
126} 132}
127 133
128fn opt_alias(p: &mut Parser) { 134fn opt_alias(p: &mut Parser) {
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 6d3e379a3..d8e825f46 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -67,8 +67,6 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
67 Err(m) => m, 67 Err(m) => m,
68 }; 68 };
69 69
70 // test pub_expr
71 // fn foo() { pub 92; } //FIXME
72 if has_attrs { 70 if has_attrs {
73 m.abandon(p); 71 m.abandon(p);
74 p.error("expected a let statement or an item after attributes in block"); 72 p.error("expected a let statement or an item after attributes in block");
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 94b93a02b..c24e6d1e0 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -67,11 +67,14 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemF
67} 67}
68 68
69pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> { 69pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> {
70 opt_visibility(p); 70 // test_err pub_expr
71 if let Some(kind) = items_without_modifiers(p) { 71 // fn foo() { pub 92; }
72 m.complete(p, kind); 72 let has_visibility = opt_visibility(p);
73 return Ok(()); 73
74 } 74 let m = match items_without_modifiers(p, m) {
75 Ok(()) => return Ok(()),
76 Err(m) => m,
77 };
75 78
76 let mut has_mods = false; 79 let mut has_mods = false;
77 80
@@ -152,10 +155,14 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
152 m.complete(p, IMPL_BLOCK); 155 m.complete(p, IMPL_BLOCK);
153 } 156 }
154 _ => { 157 _ => {
155 if !has_mods { 158 if !has_visibility && !has_mods {
156 return Err(m); 159 return Err(m);
157 } else { 160 } else {
158 p.error("expected fn, trait or impl"); 161 if has_mods {
162 p.error("expected fn, trait or impl");
163 } else {
164 p.error("expected an item");
165 }
159 m.complete(p, ERROR); 166 m.complete(p, ERROR);
160 } 167 }
161 } 168 }
@@ -163,23 +170,14 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
163 Ok(()) 170 Ok(())
164} 171}
165 172
166fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> { 173fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
167 let la = p.nth(1); 174 let la = p.nth(1);
168 let kind = match p.current() { 175 match p.current() {
169 // test extern_crate 176 // test extern_crate
170 // extern crate foo; 177 // extern crate foo;
171 EXTERN_KW if la == CRATE_KW => { 178 EXTERN_KW if la == CRATE_KW => extern_crate_item(p, m),
172 extern_crate_item(p); 179 TYPE_KW => type_def(p, m),
173 EXTERN_CRATE_ITEM 180 MOD_KW => mod_item(p, m),
174 }
175 TYPE_KW => {
176 type_def(p);
177 TYPE_ALIAS_DEF
178 }
179 MOD_KW => {
180 mod_item(p);
181 MODULE
182 }
183 STRUCT_KW => { 181 STRUCT_KW => {
184 // test struct_items 182 // test struct_items
185 // struct Foo; 183 // struct Foo;
@@ -190,14 +188,7 @@ fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
190 // a: i32, 188 // a: i32,
191 // b: f32, 189 // b: f32,
192 // } 190 // }
193 nominal::struct_def(p, STRUCT_KW); 191 nominal::struct_def(p, m, STRUCT_KW);
194 if p.at(SEMI) {
195 p.err_and_bump(
196 "expected item, found `;`\n\
197 consider removing this semicolon",
198 );
199 }
200 STRUCT_DEF
201 } 192 }
202 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { 193 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
203 // test union_items 194 // test union_items
@@ -206,25 +197,12 @@ fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
206 // a: i32, 197 // a: i32,
207 // b: f32, 198 // b: f32,
208 // } 199 // }
209 nominal::struct_def(p, UNION_KW); 200 nominal::struct_def(p, m, UNION_KW);
210 STRUCT_DEF
211 }
212 ENUM_KW => {
213 nominal::enum_def(p);
214 ENUM_DEF
215 }
216 USE_KW => {
217 use_item::use_item(p);
218 USE_ITEM
219 }
220 CONST_KW if (la == IDENT || la == MUT_KW) => {
221 consts::const_def(p);
222 CONST_DEF
223 }
224 STATIC_KW => {
225 consts::static_def(p);
226 STATIC_DEF
227 } 201 }
202 ENUM_KW => nominal::enum_def(p, m),
203 USE_KW => use_item::use_item(p, m),
204 CONST_KW if (la == IDENT || la == MUT_KW) => consts::const_def(p, m),
205 STATIC_KW => consts::static_def(p, m),
228 // test extern_block 206 // test extern_block
229 // extern {} 207 // extern {}
230 EXTERN_KW 208 EXTERN_KW
@@ -232,14 +210,20 @@ fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
232 { 210 {
233 abi(p); 211 abi(p);
234 extern_item_list(p); 212 extern_item_list(p);
235 EXTERN_BLOCK 213 m.complete(p, EXTERN_BLOCK);
236 } 214 }
237 _ => return None, 215 _ => return Err(m),
238 }; 216 };
239 Some(kind) 217 if p.at(SEMI) {
218 p.err_and_bump(
219 "expected item, found `;`\n\
220 consider removing this semicolon",
221 );
222 }
223 Ok(())
240} 224}
241 225
242fn extern_crate_item(p: &mut Parser) { 226fn extern_crate_item(p: &mut Parser, m: Marker) {
243 assert!(p.at(EXTERN_KW)); 227 assert!(p.at(EXTERN_KW));
244 p.bump(); 228 p.bump();
245 assert!(p.at(CRATE_KW)); 229 assert!(p.at(CRATE_KW));
@@ -247,6 +231,7 @@ fn extern_crate_item(p: &mut Parser) {
247 name_ref(p); 231 name_ref(p);
248 opt_alias(p); 232 opt_alias(p);
249 p.expect(SEMI); 233 p.expect(SEMI);
234 m.complete(p, EXTERN_CRATE_ITEM);
250} 235}
251 236
252pub(crate) fn extern_item_list(p: &mut Parser) { 237pub(crate) fn extern_item_list(p: &mut Parser) {
@@ -295,7 +280,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
295 280
296// test type_item 281// test type_item
297// type Foo = Bar; 282// type Foo = Bar;
298fn type_def(p: &mut Parser) { 283fn type_def(p: &mut Parser, m: Marker) {
299 assert!(p.at(TYPE_KW)); 284 assert!(p.at(TYPE_KW));
300 p.bump(); 285 p.bump();
301 286
@@ -317,9 +302,10 @@ fn type_def(p: &mut Parser) {
317 types::type_(p); 302 types::type_(p);
318 } 303 }
319 p.expect(SEMI); 304 p.expect(SEMI);
305 m.complete(p, TYPE_ALIAS_DEF);
320} 306}
321 307
322pub(crate) fn mod_item(p: &mut Parser) { 308pub(crate) fn mod_item(p: &mut Parser, m: Marker) {
323 assert!(p.at(MOD_KW)); 309 assert!(p.at(MOD_KW));
324 p.bump(); 310 p.bump();
325 311
@@ -329,6 +315,7 @@ pub(crate) fn mod_item(p: &mut Parser) {
329 } else if !p.eat(SEMI) { 315 } else if !p.eat(SEMI) {
330 p.error("expected `;` or `{`"); 316 p.error("expected `;` or `{`");
331 } 317 }
318 m.complete(p, MODULE);
332} 319}
333 320
334pub(crate) fn mod_item_list(p: &mut Parser) { 321pub(crate) fn mod_item_list(p: &mut Parser) {
diff --git a/crates/ra_parser/src/grammar/items/consts.rs b/crates/ra_parser/src/grammar/items/consts.rs
index 5a5852f83..e6e6011c6 100644
--- a/crates/ra_parser/src/grammar/items/consts.rs
+++ b/crates/ra_parser/src/grammar/items/consts.rs
@@ -1,14 +1,14 @@
1use super::*; 1use super::*;
2 2
3pub(super) fn static_def(p: &mut Parser) { 3pub(super) fn static_def(p: &mut Parser, m: Marker) {
4 const_or_static(p, STATIC_KW) 4 const_or_static(p, m, STATIC_KW, STATIC_DEF)
5} 5}
6 6
7pub(super) fn const_def(p: &mut Parser) { 7pub(super) fn const_def(p: &mut Parser, m: Marker) {
8 const_or_static(p, CONST_KW) 8 const_or_static(p, m, CONST_KW, CONST_DEF)
9} 9}
10 10
11fn const_or_static(p: &mut Parser, kw: SyntaxKind) { 11fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
12 assert!(p.at(kw)); 12 assert!(p.at(kw));
13 p.bump(); 13 p.bump();
14 p.eat(MUT_KW); // TODO: validator to forbid const mut 14 p.eat(MUT_KW); // TODO: validator to forbid const mut
@@ -18,4 +18,5 @@ fn const_or_static(p: &mut Parser, kw: SyntaxKind) {
18 expressions::expr(p); 18 expressions::expr(p);
19 } 19 }
20 p.expect(SEMI); 20 p.expect(SEMI);
21 m.complete(p, def);
21} 22}
diff --git a/crates/ra_parser/src/grammar/items/nominal.rs b/crates/ra_parser/src/grammar/items/nominal.rs
index ff9b38f9c..a3579eebd 100644
--- a/crates/ra_parser/src/grammar/items/nominal.rs
+++ b/crates/ra_parser/src/grammar/items/nominal.rs
@@ -1,6 +1,6 @@
1use super::*; 1use super::*;
2 2
3pub(super) fn struct_def(p: &mut Parser, kind: SyntaxKind) { 3pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
4 assert!(p.at(STRUCT_KW) || p.at_contextual_kw("union")); 4 assert!(p.at(STRUCT_KW) || p.at_contextual_kw("union"));
5 p.bump_remap(kind); 5 p.bump_remap(kind);
6 6
@@ -12,19 +12,16 @@ pub(super) fn struct_def(p: &mut Parser, kind: SyntaxKind) {
12 match p.current() { 12 match p.current() {
13 SEMI => { 13 SEMI => {
14 p.bump(); 14 p.bump();
15 return;
16 } 15 }
17 L_CURLY => named_field_def_list(p), 16 L_CURLY => named_field_def_list(p),
18 _ => { 17 _ => {
19 //TODO: special case `(` error message 18 //TODO: special case `(` error message
20 p.error("expected `;` or `{`"); 19 p.error("expected `;` or `{`");
21 return;
22 } 20 }
23 } 21 }
24 } 22 }
25 SEMI if kind == STRUCT_KW => { 23 SEMI if kind == STRUCT_KW => {
26 p.bump(); 24 p.bump();
27 return;
28 } 25 }
29 L_CURLY => named_field_def_list(p), 26 L_CURLY => named_field_def_list(p),
30 L_PAREN if kind == STRUCT_KW => { 27 L_PAREN if kind == STRUCT_KW => {
@@ -37,16 +34,15 @@ pub(super) fn struct_def(p: &mut Parser, kind: SyntaxKind) {
37 } 34 }
38 _ if kind == STRUCT_KW => { 35 _ if kind == STRUCT_KW => {
39 p.error("expected `;`, `{`, or `(`"); 36 p.error("expected `;`, `{`, or `(`");
40 return;
41 } 37 }
42 _ => { 38 _ => {
43 p.error("expected `{`"); 39 p.error("expected `{`");
44 return;
45 } 40 }
46 } 41 }
42 m.complete(p, STRUCT_DEF);
47} 43}
48 44
49pub(super) fn enum_def(p: &mut Parser) { 45pub(super) fn enum_def(p: &mut Parser, m: Marker) {
50 assert!(p.at(ENUM_KW)); 46 assert!(p.at(ENUM_KW));
51 p.bump(); 47 p.bump();
52 name_r(p, ITEM_RECOVERY_SET); 48 name_r(p, ITEM_RECOVERY_SET);
@@ -57,6 +53,7 @@ pub(super) fn enum_def(p: &mut Parser) {
57 } else { 53 } else {
58 p.error("expected `{`") 54 p.error("expected `{`")
59 } 55 }
56 m.complete(p, ENUM_DEF);
60} 57}
61 58
62pub(crate) fn enum_variant_list(p: &mut Parser) { 59pub(crate) fn enum_variant_list(p: &mut Parser) {
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs
index b36612726..ea2f94604 100644
--- a/crates/ra_parser/src/grammar/items/use_item.rs
+++ b/crates/ra_parser/src/grammar/items/use_item.rs
@@ -1,10 +1,11 @@
1use super::*; 1use super::*;
2 2
3pub(super) fn use_item(p: &mut Parser) { 3pub(super) fn use_item(p: &mut Parser, m: Marker) {
4 assert!(p.at(USE_KW)); 4 assert!(p.at(USE_KW));
5 p.bump(); 5 p.bump();
6 use_tree(p); 6 use_tree(p);
7 p.expect(SEMI); 7 p.expect(SEMI);
8 m.complete(p, USE_ITEM);
8} 9}
9 10
10/// Parse a use 'tree', such as `some::path` in `use some::path;` 11/// Parse a use 'tree', such as `some::path` in `use some::path;`