aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/grammar')
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs119
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs30
-rw-r--r--crates/ra_parser/src/grammar/items.rs84
3 files changed, 112 insertions, 121 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 70c71a8e1..ccbc905ab 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -43,67 +43,60 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
43 attributes::inner_attributes(p); 43 attributes::inner_attributes(p);
44 44
45 while !p.at(EOF) && !p.at(R_CURLY) { 45 while !p.at(EOF) && !p.at(R_CURLY) {
46 match p.current() { 46 // test nocontentexpr
47 // test nocontentexpr 47 // fn foo(){
48 // fn foo(){ 48 // ;;;some_expr();;;;{;;;};;;;Ok(())
49 // ;;;some_expr();;;;{;;;};;;;Ok(()) 49 // }
50 // } 50 if p.current() == SEMI {
51 SEMI => p.bump(), 51 p.bump();
52 _ => { 52 continue;
53 // test block_items 53 }
54 // fn a() { fn b() {} } 54
55 let m = p.start(); 55 // test block_items
56 let has_attrs = p.at(POUND); 56 // fn a() { fn b() {} }
57 attributes::outer_attributes(p); 57 let m = p.start();
58 if p.at(LET_KW) { 58 let has_attrs = p.at(POUND);
59 let_stmt(p, m); 59 attributes::outer_attributes(p);
60 if p.at(LET_KW) {
61 let_stmt(p, m);
62 continue;
63 }
64
65 let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) {
66 Ok(()) => continue,
67 Err(m) => m,
68 };
69
70 // test pub_expr
71 // fn foo() { pub 92; } //FIXME
72 if has_attrs {
73 m.abandon(p);
74 p.error("expected a let statement or an item after attributes in block");
75 } else {
76 let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block;
77 if p.at(R_CURLY) {
78 m.abandon(p);
79 } else {
80 // test no_semi_after_block
81 // fn foo() {
82 // if true {}
83 // loop {}
84 // match () {}
85 // while true {}
86 // for _ in () {}
87 // {}
88 // {}
89 // macro_rules! test {
90 // () => {}
91 // }
92 // test!{}
93 // }
94 if is_blocklike {
95 p.eat(SEMI);
60 } else { 96 } else {
61 match items::maybe_item(p, items::ItemFlavor::Mod) { 97 p.expect(SEMI);
62 items::MaybeItem::Item(kind) => {
63 m.complete(p, kind);
64 }
65 items::MaybeItem::Modifiers => {
66 m.abandon(p);
67 p.error("expected an item");
68 }
69 // test pub_expr
70 // fn foo() { pub 92; } //FIXME
71 items::MaybeItem::None => {
72 if has_attrs {
73 m.abandon(p);
74 p.error(
75 "expected a let statement or an item after attributes in block",
76 );
77 } else {
78 let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block;
79 if p.at(R_CURLY) {
80 m.abandon(p);
81 } else {
82 // test no_semi_after_block
83 // fn foo() {
84 // if true {}
85 // loop {}
86 // match () {}
87 // while true {}
88 // for _ in () {}
89 // {}
90 // {}
91 // macro_rules! test {
92 // () => {}
93 // }
94 // test!{}
95 // }
96 if is_blocklike {
97 p.eat(SEMI);
98 } else {
99 p.expect(SEMI);
100 }
101 m.complete(p, EXPR_STMT);
102 }
103 }
104 }
105 }
106 } 98 }
99 m.complete(p, EXPR_STMT);
107 } 100 }
108 } 101 }
109 } 102 }
@@ -155,6 +148,7 @@ fn current_op(p: &Parser) -> (u8, Op) {
155 (PLUS, EQ) => return (1, Op::Composite(PLUSEQ, 2)), 148 (PLUS, EQ) => return (1, Op::Composite(PLUSEQ, 2)),
156 (MINUS, EQ) => return (1, Op::Composite(MINUSEQ, 2)), 149 (MINUS, EQ) => return (1, Op::Composite(MINUSEQ, 2)),
157 (STAR, EQ) => return (1, Op::Composite(STAREQ, 2)), 150 (STAR, EQ) => return (1, Op::Composite(STAREQ, 2)),
151 (PERCENT, EQ) => return (1, Op::Composite(PERCENTEQ, 2)),
158 (SLASH, EQ) => return (1, Op::Composite(SLASHEQ, 2)), 152 (SLASH, EQ) => return (1, Op::Composite(SLASHEQ, 2)),
159 (PIPE, EQ) => return (1, Op::Composite(PIPEEQ, 2)), 153 (PIPE, EQ) => return (1, Op::Composite(PIPEEQ, 2)),
160 (AMP, EQ) => return (1, Op::Composite(AMPEQ, 2)), 154 (AMP, EQ) => return (1, Op::Composite(AMPEQ, 2)),
@@ -453,8 +447,13 @@ pub(crate) fn named_field_list(p: &mut Parser) {
453 p.bump(); 447 p.bump();
454 while !p.at(EOF) && !p.at(R_CURLY) { 448 while !p.at(EOF) && !p.at(R_CURLY) {
455 match p.current() { 449 match p.current() {
456 IDENT => { 450 // test struct_literal_field_with_attr
451 // fn main() {
452 // S { #[cfg(test)] field: 1 }
453 // }
454 IDENT | POUND => {
457 let m = p.start(); 455 let m = p.start();
456 attributes::outer_attributes(p);
458 name_ref(p); 457 name_ref(p);
459 if p.eat(COLON) { 458 if p.eat(COLON) {
460 expr(p); 459 expr(p);
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index 53bb26c5f..d933288cd 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -342,21 +342,6 @@ pub(crate) fn match_arm_list(p: &mut Parser) {
342 continue; 342 continue;
343 } 343 }
344 344
345 // test match_arms_outer_attributes
346 // fn foo() {
347 // match () {
348 // #[cfg(feature = "some")]
349 // _ => (),
350 // #[cfg(feature = "other")]
351 // _ => (),
352 // #[cfg(feature = "many")]
353 // #[cfg(feature = "attributes")]
354 // #[cfg(feature = "before")]
355 // _ => (),
356 // }
357 // }
358 attributes::outer_attributes(p);
359
360 // test match_arms_commas 345 // test match_arms_commas
361 // fn foo() { 346 // fn foo() {
362 // match () { 347 // match () {
@@ -387,6 +372,21 @@ pub(crate) fn match_arm_list(p: &mut Parser) {
387// } 372// }
388fn match_arm(p: &mut Parser) -> BlockLike { 373fn match_arm(p: &mut Parser) -> BlockLike {
389 let m = p.start(); 374 let m = p.start();
375 // test match_arms_outer_attributes
376 // fn foo() {
377 // match () {
378 // #[cfg(feature = "some")]
379 // _ => (),
380 // #[cfg(feature = "other")]
381 // _ => (),
382 // #[cfg(feature = "many")]
383 // #[cfg(feature = "attributes")]
384 // #[cfg(feature = "before")]
385 // _ => (),
386 // }
387 // }
388 attributes::outer_attributes(p);
389
390 patterns::pattern_list_r(p, TokenSet::empty()); 390 patterns::pattern_list_r(p, TokenSet::empty());
391 if p.at(IF_KW) { 391 if p.at(IF_KW) {
392 match_guard(p); 392 match_guard(p);
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index a057c8167..94b93a02b 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -37,52 +37,40 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![
37pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { 37pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
38 let m = p.start(); 38 let m = p.start();
39 attributes::outer_attributes(p); 39 attributes::outer_attributes(p);
40 match maybe_item(p, flavor) { 40 let m = match maybe_item(p, m, flavor) {
41 MaybeItem::Item(kind) => { 41 Ok(()) => return,
42 m.complete(p, kind); 42 Err(m) => m,
43 } 43 };
44 MaybeItem::None => { 44 if paths::is_path_start(p) {
45 if paths::is_path_start(p) { 45 match macro_call(p) {
46 match macro_call(p) { 46 BlockLike::Block => (),
47 BlockLike::Block => (), 47 BlockLike::NotBlock => {
48 BlockLike::NotBlock => { 48 p.expect(SEMI);
49 p.expect(SEMI);
50 }
51 }
52 m.complete(p, MACRO_CALL);
53 } else {
54 m.abandon(p);
55 if p.at(L_CURLY) {
56 error_block(p, "expected an item");
57 } else if p.at(R_CURLY) && !stop_on_r_curly {
58 let e = p.start();
59 p.error("unmatched `}`");
60 p.bump();
61 e.complete(p, ERROR);
62 } else if !p.at(EOF) && !p.at(R_CURLY) {
63 p.err_and_bump("expected an item");
64 } else {
65 p.error("expected an item");
66 }
67 } 49 }
68 } 50 }
69 MaybeItem::Modifiers => { 51 m.complete(p, MACRO_CALL);
70 p.error("expected fn, trait or impl"); 52 } else {
71 m.complete(p, ERROR); 53 m.abandon(p);
54 if p.at(L_CURLY) {
55 error_block(p, "expected an item");
56 } else if p.at(R_CURLY) && !stop_on_r_curly {
57 let e = p.start();
58 p.error("unmatched `}`");
59 p.bump();
60 e.complete(p, ERROR);
61 } else if !p.at(EOF) && !p.at(R_CURLY) {
62 p.err_and_bump("expected an item");
63 } else {
64 p.error("expected an item");
72 } 65 }
73 } 66 }
74} 67}
75 68
76pub(super) enum MaybeItem { 69pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> {
77 None,
78 Item(SyntaxKind),
79 Modifiers,
80}
81
82pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
83 opt_visibility(p); 70 opt_visibility(p);
84 if let Some(kind) = items_without_modifiers(p) { 71 if let Some(kind) = items_without_modifiers(p) {
85 return MaybeItem::Item(kind); 72 m.complete(p, kind);
73 return Ok(());
86 } 74 }
87 75
88 let mut has_mods = false; 76 let mut has_mods = false;
@@ -115,7 +103,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
115 } 103 }
116 104
117 // items 105 // items
118 let kind = match p.current() { 106 match p.current() {
119 // test async_fn 107 // test async_fn
120 // async fn foo() {} 108 // async fn foo() {}
121 109
@@ -135,7 +123,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
135 // unsafe fn foo() {} 123 // unsafe fn foo() {}
136 FN_KW => { 124 FN_KW => {
137 fn_def(p, flavor); 125 fn_def(p, flavor);
138 FN_DEF 126 m.complete(p, FN_DEF);
139 } 127 }
140 128
141 // test unsafe_trait 129 // test unsafe_trait
@@ -148,7 +136,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
148 // unsafe auto trait T {} 136 // unsafe auto trait T {}
149 TRAIT_KW => { 137 TRAIT_KW => {
150 traits::trait_def(p); 138 traits::trait_def(p);
151 TRAIT_DEF 139 m.complete(p, TRAIT_DEF);
152 } 140 }
153 141
154 // test unsafe_impl 142 // test unsafe_impl
@@ -161,14 +149,18 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
161 // unsafe default impl Foo {} 149 // unsafe default impl Foo {}
162 IMPL_KW => { 150 IMPL_KW => {
163 traits::impl_block(p); 151 traits::impl_block(p);
164 IMPL_BLOCK 152 m.complete(p, IMPL_BLOCK);
165 } 153 }
166 _ => { 154 _ => {
167 return if has_mods { MaybeItem::Modifiers } else { MaybeItem::None }; 155 if !has_mods {
156 return Err(m);
157 } else {
158 p.error("expected fn, trait or impl");
159 m.complete(p, ERROR);
160 }
168 } 161 }
169 }; 162 }
170 163 Ok(())
171 MaybeItem::Item(kind)
172} 164}
173 165
174fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> { 166fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {