diff options
Diffstat (limited to 'crates/ra_parser/src')
-rw-r--r-- | crates/ra_parser/src/grammar.rs | 4 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 154 | ||||
-rw-r--r-- | crates/ra_parser/src/lib.rs | 5 |
3 files changed, 91 insertions, 72 deletions
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index 5a7a55141..2c2f785d0 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -65,6 +65,10 @@ pub(crate) fn pattern(p: &mut Parser) { | |||
65 | patterns::pattern(p) | 65 | patterns::pattern(p) |
66 | } | 66 | } |
67 | 67 | ||
68 | pub(crate) fn stmt(p: &mut Parser, with_semi: bool) { | ||
69 | expressions::stmt(p, with_semi) | ||
70 | } | ||
71 | |||
68 | pub(crate) fn reparser( | 72 | pub(crate) fn reparser( |
69 | node: SyntaxKind, | 73 | node: SyntaxKind, |
70 | first_child: Option<SyntaxKind>, | 74 | first_child: Option<SyntaxKind>, |
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 295577325..06f2b45b1 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -48,88 +48,77 @@ fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool { | |||
48 | } | 48 | } |
49 | } | 49 | } |
50 | 50 | ||
51 | pub(crate) fn expr_block_contents(p: &mut Parser) { | 51 | pub(super) fn stmt(p: &mut Parser, with_semi: bool) { |
52 | // This is checked by a validator | 52 | // test block_items |
53 | attributes::inner_attributes(p); | 53 | // fn a() { fn b() {} } |
54 | 54 | let m = p.start(); | |
55 | while !p.at(EOF) && !p.at(R_CURLY) { | 55 | // test attr_on_expr_stmt |
56 | // test nocontentexpr | 56 | // fn foo() { |
57 | // fn foo(){ | 57 | // #[A] foo(); |
58 | // ;;;some_expr();;;;{;;;};;;;Ok(()) | 58 | // #[B] bar!{} |
59 | // } | 59 | // #[C] #[D] {} |
60 | if p.current() == SEMI { | 60 | // #[D] return (); |
61 | p.bump(); | 61 | // } |
62 | continue; | 62 | let has_attrs = p.at(POUND); |
63 | } | 63 | attributes::outer_attributes(p); |
64 | 64 | ||
65 | // test block_items | 65 | if p.at(LET_KW) { |
66 | // fn a() { fn b() {} } | 66 | let_stmt(p, m, with_semi); |
67 | let m = p.start(); | 67 | return; |
68 | // test attr_on_expr_stmt | 68 | } |
69 | // fn foo() { | ||
70 | // #[A] foo(); | ||
71 | // #[B] bar!{} | ||
72 | // #[C] #[D] {} | ||
73 | // #[D] return (); | ||
74 | // } | ||
75 | let has_attrs = p.at(POUND); | ||
76 | attributes::outer_attributes(p); | ||
77 | if p.at(LET_KW) { | ||
78 | let_stmt(p, m); | ||
79 | continue; | ||
80 | } | ||
81 | 69 | ||
82 | let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) { | 70 | let m = match items::maybe_item(p, m, items::ItemFlavor::Mod) { |
83 | Ok(()) => continue, | 71 | Ok(()) => return, |
84 | Err(m) => m, | 72 | Err(m) => m, |
85 | }; | 73 | }; |
86 | 74 | ||
87 | let (cm, blocklike) = expr_stmt(p); | 75 | let (cm, blocklike) = expr_stmt(p); |
88 | let kind = cm.as_ref().map(|cm| cm.kind()).unwrap_or(ERROR); | 76 | let kind = cm.as_ref().map(|cm| cm.kind()).unwrap_or(ERROR); |
89 | 77 | ||
90 | if has_attrs && !is_expr_stmt_attr_allowed(kind) { | 78 | if has_attrs && !is_expr_stmt_attr_allowed(kind) { |
91 | // test_err attr_on_expr_not_allowed | 79 | // test_err attr_on_expr_not_allowed |
92 | // fn foo() { | 80 | // fn foo() { |
93 | // #[A] 1 + 2; | 81 | // #[A] 1 + 2; |
94 | // #[B] if true {}; | 82 | // #[B] if true {}; |
95 | // } | 83 | // } |
96 | p.error(format!("attributes are not allowed on {:?}", kind)); | 84 | p.error(format!("attributes are not allowed on {:?}", kind)); |
97 | } | 85 | } |
98 | 86 | ||
99 | if p.at(R_CURLY) { | 87 | if p.at(R_CURLY) { |
100 | // test attr_on_last_expr_in_block | 88 | // test attr_on_last_expr_in_block |
101 | // fn foo() { | 89 | // fn foo() { |
102 | // { #[A] bar!()? } | 90 | // { #[A] bar!()? } |
103 | // #[B] &() | 91 | // #[B] &() |
104 | // } | 92 | // } |
105 | if let Some(cm) = cm { | 93 | if let Some(cm) = cm { |
106 | cm.undo_completion(p).abandon(p); | 94 | cm.undo_completion(p).abandon(p); |
107 | m.complete(p, kind); | 95 | m.complete(p, kind); |
108 | } else { | ||
109 | m.abandon(p); | ||
110 | } | ||
111 | } else { | 96 | } else { |
112 | // test no_semi_after_block | 97 | m.abandon(p); |
113 | // fn foo() { | 98 | } |
114 | // if true {} | 99 | } else { |
115 | // loop {} | 100 | // test no_semi_after_block |
116 | // match () {} | 101 | // fn foo() { |
117 | // while true {} | 102 | // if true {} |
118 | // for _ in () {} | 103 | // loop {} |
119 | // {} | 104 | // match () {} |
120 | // {} | 105 | // while true {} |
121 | // macro_rules! test { | 106 | // for _ in () {} |
122 | // () => {} | 107 | // {} |
123 | // } | 108 | // {} |
124 | // test!{} | 109 | // macro_rules! test { |
125 | // } | 110 | // () => {} |
111 | // } | ||
112 | // test!{} | ||
113 | // } | ||
114 | if with_semi { | ||
126 | if blocklike.is_block() { | 115 | if blocklike.is_block() { |
127 | p.eat(SEMI); | 116 | p.eat(SEMI); |
128 | } else { | 117 | } else { |
129 | p.expect(SEMI); | 118 | p.expect(SEMI); |
130 | } | 119 | } |
131 | m.complete(p, EXPR_STMT); | ||
132 | } | 120 | } |
121 | m.complete(p, EXPR_STMT); | ||
133 | } | 122 | } |
134 | 123 | ||
135 | // test let_stmt; | 124 | // test let_stmt; |
@@ -139,7 +128,7 @@ pub(crate) fn expr_block_contents(p: &mut Parser) { | |||
139 | // let c = 92; | 128 | // let c = 92; |
140 | // let d: i32 = 92; | 129 | // let d: i32 = 92; |
141 | // } | 130 | // } |
142 | fn let_stmt(p: &mut Parser, m: Marker) { | 131 | fn let_stmt(p: &mut Parser, m: Marker, with_semi: bool) { |
143 | assert!(p.at(LET_KW)); | 132 | assert!(p.at(LET_KW)); |
144 | p.bump(); | 133 | p.bump(); |
145 | patterns::pattern(p); | 134 | patterns::pattern(p); |
@@ -149,11 +138,32 @@ pub(crate) fn expr_block_contents(p: &mut Parser) { | |||
149 | if p.eat(EQ) { | 138 | if p.eat(EQ) { |
150 | expressions::expr(p); | 139 | expressions::expr(p); |
151 | } | 140 | } |
152 | p.expect(SEMI); | 141 | |
142 | if with_semi { | ||
143 | p.expect(SEMI); | ||
144 | } | ||
153 | m.complete(p, LET_STMT); | 145 | m.complete(p, LET_STMT); |
154 | } | 146 | } |
155 | } | 147 | } |
156 | 148 | ||
149 | pub(crate) fn expr_block_contents(p: &mut Parser) { | ||
150 | // This is checked by a validator | ||
151 | attributes::inner_attributes(p); | ||
152 | |||
153 | while !p.at(EOF) && !p.at(R_CURLY) { | ||
154 | // test nocontentexpr | ||
155 | // fn foo(){ | ||
156 | // ;;;some_expr();;;;{;;;};;;;Ok(()) | ||
157 | // } | ||
158 | if p.current() == SEMI { | ||
159 | p.bump(); | ||
160 | continue; | ||
161 | } | ||
162 | |||
163 | stmt(p, true) | ||
164 | } | ||
165 | } | ||
166 | |||
157 | #[derive(Clone, Copy)] | 167 | #[derive(Clone, Copy)] |
158 | struct Restrictions { | 168 | struct Restrictions { |
159 | forbid_structs: bool, | 169 | forbid_structs: bool, |
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs index 56755c394..9133c1b8a 100644 --- a/crates/ra_parser/src/lib.rs +++ b/crates/ra_parser/src/lib.rs | |||
@@ -88,6 +88,11 @@ pub fn parse_pat(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { | |||
88 | parse_from_tokens(token_source, tree_sink, grammar::pattern); | 88 | parse_from_tokens(token_source, tree_sink, grammar::pattern); |
89 | } | 89 | } |
90 | 90 | ||
91 | /// Parse given tokens into the given sink as a statement | ||
92 | pub fn parse_stmt(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink, with_semi: bool) { | ||
93 | parse_from_tokens(token_source, tree_sink, |p| grammar::stmt(p, with_semi)); | ||
94 | } | ||
95 | |||
91 | /// A parsing function for a specific braced-block. | 96 | /// A parsing function for a specific braced-block. |
92 | pub struct Reparser(fn(&mut parser::Parser)); | 97 | pub struct Reparser(fn(&mut parser::Parser)); |
93 | 98 | ||