diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 20 | ||||
-rw-r--r-- | crates/ra_parser/src/parser.rs | 57 |
2 files changed, 37 insertions, 40 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index c8ce07179..73e1acd5a 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -82,16 +82,15 @@ pub(crate) fn expr_block_contents(p: &mut Parser) { | |||
82 | }; | 82 | }; |
83 | 83 | ||
84 | let (cm, blocklike) = expr_stmt(p); | 84 | let (cm, blocklike) = expr_stmt(p); |
85 | let kind = cm.as_ref().map(|cm| cm.kind()).unwrap_or(ERROR); | ||
85 | 86 | ||
86 | if let Some(cm) = &cm { | 87 | if has_attrs && !is_expr_stmt_attr_allowed(kind) { |
87 | if has_attrs && !is_expr_stmt_attr_allowed(cm.kind()) { | 88 | // test_err attr_on_expr_not_allowed |
88 | // test_err attr_on_expr_not_allowed | 89 | // fn foo() { |
89 | // fn foo() { | 90 | // #[A] 1 + 2; |
90 | // #[A] 1 + 2; | 91 | // #[B] if true {}; |
91 | // #[B] if true {}; | 92 | // } |
92 | // } | 93 | p.error(format!("attributes are not allowed on {:?}", kind)); |
93 | p.error(format!("attributes are not allowed on {:?}", cm.kind())); | ||
94 | } | ||
95 | } | 94 | } |
96 | 95 | ||
97 | if p.at(R_CURLY) { | 96 | if p.at(R_CURLY) { |
@@ -101,7 +100,8 @@ pub(crate) fn expr_block_contents(p: &mut Parser) { | |||
101 | // #[B] &() | 100 | // #[B] &() |
102 | // } | 101 | // } |
103 | if let Some(cm) = cm { | 102 | if let Some(cm) = cm { |
104 | m.contract_child(p, cm); | 103 | cm.undo_completion(p).abandon(p); |
104 | m.complete(p, kind); | ||
105 | } else { | 105 | } else { |
106 | m.abandon(p); | 106 | m.abandon(p); |
107 | } | 107 | } |
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs index fa036bdbf..3c326452b 100644 --- a/crates/ra_parser/src/parser.rs +++ b/crates/ra_parser/src/parser.rs | |||
@@ -212,8 +212,9 @@ impl Marker { | |||
212 | } | 212 | } |
213 | _ => unreachable!(), | 213 | _ => unreachable!(), |
214 | } | 214 | } |
215 | let finish_pos = p.events.len() as u32; | ||
215 | p.push_event(Event::Finish); | 216 | p.push_event(Event::Finish); |
216 | CompletedMarker::new(self.pos, kind) | 217 | CompletedMarker::new(self.pos, finish_pos, kind) |
217 | } | 218 | } |
218 | 219 | ||
219 | /// Abandons the syntax tree node. All its children | 220 | /// Abandons the syntax tree node. All its children |
@@ -228,36 +229,17 @@ impl Marker { | |||
228 | } | 229 | } |
229 | } | 230 | } |
230 | } | 231 | } |
231 | |||
232 | /// Contract a node `cm` and complete as `cm`'s `kind`. | ||
233 | /// `cm` must be a child of `m` to work correctly. | ||
234 | /// ```text | ||
235 | /// m--A m--A | ||
236 | /// +--cm--B -> +--B | ||
237 | /// +--C C | ||
238 | /// | ||
239 | /// [m: TOMBSTONE, A, cm: Start(k), B, Finish, C] | ||
240 | /// [m: Start(k), A, cm: TOMBSTONE, B, Finish, C] | ||
241 | /// ``` | ||
242 | pub(crate) fn contract_child(mut self, p: &mut Parser, cm: CompletedMarker) -> CompletedMarker { | ||
243 | self.bomb.defuse(); | ||
244 | match p.events[self.pos as usize] { | ||
245 | Event::Start { kind: ref mut slot, .. } => *slot = cm.kind(), | ||
246 | _ => unreachable!(), | ||
247 | }; | ||
248 | match p.events[cm.0 as usize] { | ||
249 | Event::Start { kind: ref mut slot, .. } => *slot = TOMBSTONE, | ||
250 | _ => unreachable!(), | ||
251 | }; | ||
252 | CompletedMarker::new(self.pos, cm.kind()) | ||
253 | } | ||
254 | } | 232 | } |
255 | 233 | ||
256 | pub(crate) struct CompletedMarker(u32, SyntaxKind); | 234 | pub(crate) struct CompletedMarker { |
235 | start_pos: u32, | ||
236 | finish_pos: u32, | ||
237 | kind: SyntaxKind, | ||
238 | } | ||
257 | 239 | ||
258 | impl CompletedMarker { | 240 | impl CompletedMarker { |
259 | fn new(pos: u32, kind: SyntaxKind) -> Self { | 241 | fn new(start_pos: u32, finish_pos: u32, kind: SyntaxKind) -> Self { |
260 | CompletedMarker(pos, kind) | 242 | CompletedMarker { start_pos, finish_pos, kind } |
261 | } | 243 | } |
262 | 244 | ||
263 | /// This method allows to create a new node which starts | 245 | /// This method allows to create a new node which starts |
@@ -274,17 +256,32 @@ impl CompletedMarker { | |||
274 | /// distance to `NEWSTART` into forward_parent(=2 in this case); | 256 | /// distance to `NEWSTART` into forward_parent(=2 in this case); |
275 | pub(crate) fn precede(self, p: &mut Parser) -> Marker { | 257 | pub(crate) fn precede(self, p: &mut Parser) -> Marker { |
276 | let new_pos = p.start(); | 258 | let new_pos = p.start(); |
277 | let idx = self.0 as usize; | 259 | let idx = self.start_pos as usize; |
278 | match p.events[idx] { | 260 | match p.events[idx] { |
279 | Event::Start { ref mut forward_parent, .. } => { | 261 | Event::Start { ref mut forward_parent, .. } => { |
280 | *forward_parent = Some(new_pos.pos - self.0); | 262 | *forward_parent = Some(new_pos.pos - self.start_pos); |
281 | } | 263 | } |
282 | _ => unreachable!(), | 264 | _ => unreachable!(), |
283 | } | 265 | } |
284 | new_pos | 266 | new_pos |
285 | } | 267 | } |
286 | 268 | ||
269 | /// Undo this completion and turns into a `Marker` | ||
270 | pub(crate) fn undo_completion(self, p: &mut Parser) -> Marker { | ||
271 | let start_idx = self.start_pos as usize; | ||
272 | let finish_idx = self.finish_pos as usize; | ||
273 | match p.events[start_idx] { | ||
274 | Event::Start { ref mut kind, forward_parent: None } => *kind = TOMBSTONE, | ||
275 | _ => unreachable!(), | ||
276 | } | ||
277 | match p.events[finish_idx] { | ||
278 | ref mut slot @ Event::Finish => *slot = Event::tombstone(), | ||
279 | _ => unreachable!(), | ||
280 | } | ||
281 | Marker::new(self.start_pos) | ||
282 | } | ||
283 | |||
287 | pub(crate) fn kind(&self) -> SyntaxKind { | 284 | pub(crate) fn kind(&self) -> SyntaxKind { |
288 | self.1 | 285 | self.kind |
289 | } | 286 | } |
290 | } | 287 | } |