diff options
Diffstat (limited to 'crates/ra_parser/src/grammar')
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 119 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/expressions/atom.rs | 30 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/items.rs | 84 |
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 | // } |
388 | fn match_arm(p: &mut Parser) -> BlockLike { | 373 | fn 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![ | |||
37 | pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { | 37 | pub(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 | ||
76 | pub(super) enum MaybeItem { | 69 | pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> { |
77 | None, | ||
78 | Item(SyntaxKind), | ||
79 | Modifiers, | ||
80 | } | ||
81 | |||
82 | pub(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 | ||
174 | fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> { | 166 | fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> { |