aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar/expressions.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-09-09 12:52:31 +0100
committerAleksey Kladov <[email protected]>2019-09-10 13:46:39 +0100
commit40170885e799ebdefb24ed00865cd1c7800af491 (patch)
tree1b7a6f1eaaa70e1db70dd5763377fd877636a55d /crates/ra_parser/src/grammar/expressions.rs
parente2ebb467bdf3ebb7d29260adb95c56594c6db282 (diff)
WIP: switch to fully decomposed tokens internally
Diffstat (limited to 'crates/ra_parser/src/grammar/expressions.rs')
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs198
1 files changed, 107 insertions, 91 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 30036eb46..ea04b9458 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -212,52 +212,48 @@ struct Restrictions {
212 prefer_stmt: bool, 212 prefer_stmt: bool,
213} 213}
214 214
215enum Op { 215/// Binding powers of operators for a Pratt parser.
216 Simple, 216///
217 Composite(SyntaxKind, u8), 217/// See https://www.oilshell.org/blog/2016/11/03.html
218} 218#[rustfmt::skip]
219 219fn current_op(p: &Parser) -> (u8, SyntaxKind) {
220fn current_op(p: &Parser) -> (u8, Op) { 220 const NOT_AN_OP: (u8, SyntaxKind) = (0, T![@]);
221 if let Some(t) = p.current3() { 221 match p.current() {
222 match t { 222 T![|] if p.at(T![||]) => (3, T![||]),
223 (T![<], T![<], T![=]) => return (1, Op::Composite(T![<<=], 3)), 223 T![|] if p.at(T![|=]) => (1, T![|=]),
224 (T![>], T![>], T![=]) => return (1, Op::Composite(T![>>=], 3)), 224 T![|] => (6, T![|]),
225 _ => (), 225 T![>] if p.at(T![>>=]) => (1, T![>>=]),
226 } 226 T![>] if p.at(T![>>]) => (9, T![>>]),
227 } 227 T![>] if p.at(T![>=]) => (5, T![>=]),
228 228 T![>] => (5, T![>]),
229 if let Some(t) = p.current2() { 229 T![=] if p.at(T![=>]) => NOT_AN_OP,
230 match t { 230 T![=] if p.at(T![==]) => (5, T![==]),
231 (T![+], T![=]) => return (1, Op::Composite(T![+=], 2)), 231 T![=] => (1, T![=]),
232 (T![-], T![=]) => return (1, Op::Composite(T![-=], 2)), 232 T![<] if p.at(T![<=]) => (5, T![<=]),
233 (T![*], T![=]) => return (1, Op::Composite(T![*=], 2)), 233 T![<] if p.at(T![<<=]) => (1, T![<<=]),
234 (T![%], T![=]) => return (1, Op::Composite(T![%=], 2)), 234 T![<] if p.at(T![<<]) => (9, T![<<]),
235 (T![/], T![=]) => return (1, Op::Composite(T![/=], 2)), 235 T![<] => (5, T![<]),
236 (T![|], T![=]) => return (1, Op::Composite(T![|=], 2)), 236 T![+] if p.at(T![+=]) => (1, T![+=]),
237 (T![&], T![=]) => return (1, Op::Composite(T![&=], 2)), 237 T![+] => (10, T![+]),
238 (T![^], T![=]) => return (1, Op::Composite(T![^=], 2)), 238 T![^] if p.at(T![^=]) => (1, T![^=]),
239 (T![|], T![|]) => return (3, Op::Composite(T![||], 2)), 239 T![^] => (7, T![^]),
240 (T![&], T![&]) => return (4, Op::Composite(T![&&], 2)), 240 T![%] if p.at(T![%=]) => (1, T![%=]),
241 (T![<], T![=]) => return (5, Op::Composite(T![<=], 2)), 241 T![%] => (11, T![%]),
242 (T![>], T![=]) => return (5, Op::Composite(T![>=], 2)), 242 T![&] if p.at(T![&=]) => (1, T![&=]),
243 (T![<], T![<]) => return (9, Op::Composite(T![<<], 2)), 243 T![&] if p.at(T![&&]) => (4, T![&&]),
244 (T![>], T![>]) => return (9, Op::Composite(T![>>], 2)), 244 T![&] => (8, T![&]),
245 _ => (), 245 T![/] if p.at(T![/=]) => (1, T![/=]),
246 } 246 T![/] => (11, T![/]),
247 T![*] if p.at(T![*=]) => (1, T![*=]),
248 T![*] => (11, T![*]),
249 T![.] if p.at(T![..=]) => (2, T![..=]),
250 T![.] if p.at(T![..]) => (2, T![..]),
251 T![!] if p.at(T![!=]) => (5, T![!=]),
252 T![-] if p.at(T![-=]) => (1, T![-=]),
253 T![-] => (10, T![-]),
254
255 _ => NOT_AN_OP
247 } 256 }
248
249 let bp = match p.current() {
250 T![=] => 1,
251 T![..] | T![..=] => 2,
252 T![==] | T![!=] | T![<] | T![>] => 5,
253 T![|] => 6,
254 T![^] => 7,
255 T![&] => 8,
256 T![-] | T![+] => 10,
257 T![*] | T![/] | T![%] => 11,
258 _ => 0,
259 };
260 (bp, Op::Simple)
261} 257}
262 258
263// Parses expression with binding power of at least bp. 259// Parses expression with binding power of at least bp.
@@ -308,12 +304,7 @@ fn expr_bp(
308 break; 304 break;
309 } 305 }
310 let m = lhs.precede(p); 306 let m = lhs.precede(p);
311 match op { 307 p.bump(op);
312 Op::Simple => p.bump_any(),
313 Op::Composite(kind, n) => {
314 p.bump_compound(kind, n);
315 }
316 }
317 308
318 expr_bp(p, r, op_bp + 1, dollar_lvl); 309 expr_bp(p, r, op_bp + 1, dollar_lvl);
319 lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); 310 lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
@@ -321,8 +312,7 @@ fn expr_bp(
321 (Some(lhs), BlockLike::NotBlock) 312 (Some(lhs), BlockLike::NotBlock)
322} 313}
323 314
324const LHS_FIRST: TokenSet = 315const LHS_FIRST: TokenSet = atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOT, MINUS]);
325 atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOTDOT, DOTDOTEQ, MINUS]);
326 316
327fn lhs( 317fn lhs(
328 p: &mut Parser, 318 p: &mut Parser,
@@ -353,17 +343,20 @@ fn lhs(
353 p.bump_any(); 343 p.bump_any();
354 PREFIX_EXPR 344 PREFIX_EXPR
355 } 345 }
356 // test full_range_expr
357 // fn foo() { xs[..]; }
358 T![..] | T![..=] => {
359 m = p.start();
360 p.bump_any();
361 if p.at_ts(EXPR_FIRST) {
362 expr_bp(p, r, 2, dollar_lvl);
363 }
364 return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
365 }
366 _ => { 346 _ => {
347 // test full_range_expr
348 // fn foo() { xs[..]; }
349 for &op in [T![..=], T![..]].iter() {
350 if p.at(op) {
351 m = p.start();
352 p.bump(op);
353 if p.at_ts(EXPR_FIRST) {
354 expr_bp(p, r, 2, dollar_lvl);
355 }
356 return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
357 }
358 }
359
367 // test expression_after_block 360 // test expression_after_block
368 // fn foo() { 361 // fn foo() {
369 // let mut p = F{x: 5}; 362 // let mut p = F{x: 5};
@@ -399,29 +392,13 @@ fn postfix_expr(
399 // } 392 // }
400 T!['('] if allow_calls => call_expr(p, lhs), 393 T!['('] if allow_calls => call_expr(p, lhs),
401 T!['['] if allow_calls => index_expr(p, lhs), 394 T!['['] if allow_calls => index_expr(p, lhs),
402 T![.] if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::]) => { 395 T![.] => match postfix_dot_expr(p, lhs) {
403 method_call_expr(p, lhs) 396 Ok(it) => it,
404 } 397 Err(it) => {
405 T![.] if p.nth(1) == AWAIT_KW => { 398 lhs = it;
406 // test await_expr 399 break;
407 // fn foo() { 400 }
408 // x.await; 401 },
409 // x.0.await;
410 // x.0().await?.hello();
411 // }
412 let m = lhs.precede(p);
413 p.bump_any();
414 p.bump_any();
415 m.complete(p, AWAIT_EXPR)
416 }
417 T![.] => field_expr(p, lhs),
418 // test postfix_range
419 // fn foo() { let x = 1..; }
420 T![..] | T![..=] if !EXPR_FIRST.contains(p.nth(1)) => {
421 let m = lhs.precede(p);
422 p.bump_any();
423 m.complete(p, RANGE_EXPR)
424 }
425 T![?] => try_expr(p, lhs), 402 T![?] => try_expr(p, lhs),
426 T![as] => cast_expr(p, lhs), 403 T![as] => cast_expr(p, lhs),
427 _ => break, 404 _ => break,
@@ -429,7 +406,46 @@ fn postfix_expr(
429 allow_calls = true; 406 allow_calls = true;
430 block_like = BlockLike::NotBlock; 407 block_like = BlockLike::NotBlock;
431 } 408 }
432 (lhs, block_like) 409 return (lhs, block_like);
410
411 fn postfix_dot_expr(
412 p: &mut Parser,
413 lhs: CompletedMarker,
414 ) -> Result<CompletedMarker, CompletedMarker> {
415 assert!(p.at(T![.]));
416 if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) {
417 return Ok(method_call_expr(p, lhs));
418 }
419
420 // test await_expr
421 // fn foo() {
422 // x.await;
423 // x.0.await;
424 // x.0().await?.hello();
425 // }
426 if p.nth(1) == T![await] {
427 let m = lhs.precede(p);
428 p.bump(T![.]);
429 p.bump(T![await]);
430 return Ok(m.complete(p, AWAIT_EXPR));
431 }
432
433 // test postfix_range
434 // fn foo() { let x = 1..; }
435 for &(op, la) in [(T![..=], 3), (T![..], 2)].iter() {
436 if p.at(op) {
437 return if EXPR_FIRST.contains(p.nth(la)) {
438 Err(lhs)
439 } else {
440 let m = lhs.precede(p);
441 p.bump(op);
442 Ok(m.complete(p, RANGE_EXPR))
443 };
444 }
445 }
446
447 Ok(field_expr(p, lhs))
448 }
433} 449}
434 450
435// test call_expr 451// test call_expr
@@ -465,7 +481,7 @@ fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
465// y.bar::<T>(1, 2,); 481// y.bar::<T>(1, 2,);
466// } 482// }
467fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 483fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
468 assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::])); 484 assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])));
469 let m = lhs.precede(p); 485 let m = lhs.precede(p);
470 p.bump_any(); 486 p.bump_any();
471 name_ref(p); 487 name_ref(p);
@@ -567,7 +583,7 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
567 record_field_list(p); 583 record_field_list(p);
568 (m.complete(p, RECORD_LIT), BlockLike::NotBlock) 584 (m.complete(p, RECORD_LIT), BlockLike::NotBlock)
569 } 585 }
570 T![!] => { 586 T![!] if !p.at(T![!=]) => {
571 let block_like = items::macro_call_after_excl(p); 587 let block_like = items::macro_call_after_excl(p);
572 (m.complete(p, MACRO_CALL), block_like) 588 (m.complete(p, MACRO_CALL), block_like)
573 } 589 }
@@ -601,8 +617,8 @@ pub(crate) fn record_field_list(p: &mut Parser) {
601 } 617 }
602 m.complete(p, RECORD_FIELD); 618 m.complete(p, RECORD_FIELD);
603 } 619 }
604 T![..] => { 620 T![.] if p.at(T![..]) => {
605 p.bump_any(); 621 p.bump(T![..]);
606 expr(p); 622 expr(p);
607 } 623 }
608 T!['{'] => error_block(p, "expected a field"), 624 T!['{'] => error_block(p, "expected a field"),