diff options
Diffstat (limited to 'crates/ra_parser/src/grammar/expressions.rs')
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 121 |
1 files changed, 63 insertions, 58 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 70c71a8e1..5a3b9f589 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -43,65 +43,64 @@ 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 | match items::maybe_item(p, items::ItemFlavor::Mod) { | ||
66 | items::MaybeItem::Item(kind) => { | ||
67 | m.complete(p, kind); | ||
68 | } | ||
69 | items::MaybeItem::Modifiers => { | ||
70 | m.abandon(p); | ||
71 | p.error("expected an item"); | ||
72 | } | ||
73 | // test pub_expr | ||
74 | // fn foo() { pub 92; } //FIXME | ||
75 | items::MaybeItem::None => { | ||
76 | if has_attrs { | ||
77 | m.abandon(p); | ||
78 | p.error("expected a let statement or an item after attributes in block"); | ||
60 | } else { | 79 | } else { |
61 | match items::maybe_item(p, items::ItemFlavor::Mod) { | 80 | let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block; |
62 | items::MaybeItem::Item(kind) => { | 81 | if p.at(R_CURLY) { |
63 | m.complete(p, kind); | 82 | m.abandon(p); |
64 | } | 83 | } else { |
65 | items::MaybeItem::Modifiers => { | 84 | // test no_semi_after_block |
66 | m.abandon(p); | 85 | // fn foo() { |
67 | p.error("expected an item"); | 86 | // if true {} |
68 | } | 87 | // loop {} |
69 | // test pub_expr | 88 | // match () {} |
70 | // fn foo() { pub 92; } //FIXME | 89 | // while true {} |
71 | items::MaybeItem::None => { | 90 | // for _ in () {} |
72 | if has_attrs { | 91 | // {} |
73 | m.abandon(p); | 92 | // {} |
74 | p.error( | 93 | // macro_rules! test { |
75 | "expected a let statement or an item after attributes in block", | 94 | // () => {} |
76 | ); | 95 | // } |
77 | } else { | 96 | // test!{} |
78 | let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block; | 97 | // } |
79 | if p.at(R_CURLY) { | 98 | if is_blocklike { |
80 | m.abandon(p); | 99 | p.eat(SEMI); |
81 | } else { | 100 | } else { |
82 | // test no_semi_after_block | 101 | p.expect(SEMI); |
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 | } | 102 | } |
103 | m.complete(p, EXPR_STMT); | ||
105 | } | 104 | } |
106 | } | 105 | } |
107 | } | 106 | } |
@@ -155,6 +154,7 @@ fn current_op(p: &Parser) -> (u8, Op) { | |||
155 | (PLUS, EQ) => return (1, Op::Composite(PLUSEQ, 2)), | 154 | (PLUS, EQ) => return (1, Op::Composite(PLUSEQ, 2)), |
156 | (MINUS, EQ) => return (1, Op::Composite(MINUSEQ, 2)), | 155 | (MINUS, EQ) => return (1, Op::Composite(MINUSEQ, 2)), |
157 | (STAR, EQ) => return (1, Op::Composite(STAREQ, 2)), | 156 | (STAR, EQ) => return (1, Op::Composite(STAREQ, 2)), |
157 | (PERCENT, EQ) => return (1, Op::Composite(PERCENTEQ, 2)), | ||
158 | (SLASH, EQ) => return (1, Op::Composite(SLASHEQ, 2)), | 158 | (SLASH, EQ) => return (1, Op::Composite(SLASHEQ, 2)), |
159 | (PIPE, EQ) => return (1, Op::Composite(PIPEEQ, 2)), | 159 | (PIPE, EQ) => return (1, Op::Composite(PIPEEQ, 2)), |
160 | (AMP, EQ) => return (1, Op::Composite(AMPEQ, 2)), | 160 | (AMP, EQ) => return (1, Op::Composite(AMPEQ, 2)), |
@@ -453,8 +453,13 @@ pub(crate) fn named_field_list(p: &mut Parser) { | |||
453 | p.bump(); | 453 | p.bump(); |
454 | while !p.at(EOF) && !p.at(R_CURLY) { | 454 | while !p.at(EOF) && !p.at(R_CURLY) { |
455 | match p.current() { | 455 | match p.current() { |
456 | IDENT => { | 456 | // test struct_literal_field_with_attr |
457 | // fn main() { | ||
458 | // S { #[cfg(test)] field: 1 } | ||
459 | // } | ||
460 | IDENT | POUND => { | ||
457 | let m = p.start(); | 461 | let m = p.start(); |
462 | attributes::outer_attributes(p); | ||
458 | name_ref(p); | 463 | name_ref(p); |
459 | if p.eat(COLON) { | 464 | if p.eat(COLON) { |
460 | expr(p); | 465 | expr(p); |