aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-10-03 16:03:29 +0100
committerGitHub <[email protected]>2019-10-03 16:03:29 +0100
commit7d1bb35fb179b7e55ceb9c5354d9d74bffb8ca63 (patch)
tree9a6b2a477a371499f7a9012b26bf639acd801cb6 /crates
parente1c367595139f109fb6f53811bed7d67a384793e (diff)
parent9638adaa40d22adcf9b4002d95a13977c0f1436f (diff)
Merge #1950
1950: Fix parsing of block expressions in "forbid_structs" contexts. r=kjeremy a=goffrie Forbidding block expressions entirely is too strict; instead, we should only forbid them in contexts where we are parsing an optional RHS (i.e. the RHS of a range expression). Fixes #1773. Co-authored-by: Geoffry Song <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs25
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs10
-rw-r--r--crates/ra_syntax/src/grammar.ron2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt34
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt43
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt65
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt107
11 files changed, 242 insertions, 54 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 413ecb278..74b23e2f7 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -335,7 +335,13 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)>
335 // } 335 // }
336 // 336 //
337 let (lhs, blocklike) = atom::atom_expr(p, r)?; 337 let (lhs, blocklike) = atom::atom_expr(p, r)?;
338 return Some(postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block()))); 338 return Some(postfix_expr(
339 p,
340 lhs,
341 blocklike,
342 !(r.prefer_stmt && blocklike.is_block()),
343 r.forbid_structs,
344 ));
339 } 345 }
340 }; 346 };
341 expr_bp(p, r, 255); 347 expr_bp(p, r, 255);
@@ -350,6 +356,7 @@ fn postfix_expr(
350 // `while true {break}; ();` 356 // `while true {break}; ();`
351 mut block_like: BlockLike, 357 mut block_like: BlockLike,
352 mut allow_calls: bool, 358 mut allow_calls: bool,
359 forbid_structs: bool,
353) -> (CompletedMarker, BlockLike) { 360) -> (CompletedMarker, BlockLike) {
354 loop { 361 loop {
355 lhs = match p.current() { 362 lhs = match p.current() {
@@ -363,7 +370,7 @@ fn postfix_expr(
363 // } 370 // }
364 T!['('] if allow_calls => call_expr(p, lhs), 371 T!['('] if allow_calls => call_expr(p, lhs),
365 T!['['] if allow_calls => index_expr(p, lhs), 372 T!['['] if allow_calls => index_expr(p, lhs),
366 T![.] => match postfix_dot_expr(p, lhs) { 373 T![.] => match postfix_dot_expr(p, lhs, forbid_structs) {
367 Ok(it) => it, 374 Ok(it) => it,
368 Err(it) => { 375 Err(it) => {
369 lhs = it; 376 lhs = it;
@@ -382,6 +389,7 @@ fn postfix_expr(
382 fn postfix_dot_expr( 389 fn postfix_dot_expr(
383 p: &mut Parser, 390 p: &mut Parser,
384 lhs: CompletedMarker, 391 lhs: CompletedMarker,
392 forbid_structs: bool,
385 ) -> Result<CompletedMarker, CompletedMarker> { 393 ) -> Result<CompletedMarker, CompletedMarker> {
386 assert!(p.at(T![.])); 394 assert!(p.at(T![.]));
387 if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) { 395 if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) {
@@ -402,10 +410,17 @@ fn postfix_expr(
402 } 410 }
403 411
404 // test postfix_range 412 // test postfix_range
405 // fn foo() { let x = 1..; } 413 // fn foo() {
406 for &(op, la) in [(T![..=], 3), (T![..], 2)].iter() { 414 // let x = 1..;
415 // match 1.. { _ => () };
416 // match a.b()..S { _ => () };
417 // }
418 for &(op, la) in &[(T![..=], 3), (T![..], 2)] {
407 if p.at(op) { 419 if p.at(op) {
408 return if EXPR_FIRST.contains(p.nth(la)) { 420 let next_token = p.nth(la);
421 let has_trailing_expression =
422 !(forbid_structs && next_token == T!['{']) && EXPR_FIRST.contains(next_token);
423 return if has_trailing_expression {
409 Err(lhs) 424 Err(lhs)
410 } else { 425 } else {
411 let m = lhs.precede(p); 426 let m = lhs.precede(p);
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index a52bdb3ea..7454005c4 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -121,11 +121,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
121 // break; 121 // break;
122 // } 122 // }
123 // } 123 // }
124 if r.forbid_structs { 124 block_expr(p, None)
125 return None;
126 } else {
127 block_expr(p, None)
128 }
129 } 125 }
130 T![return] => return_expr(p), 126 T![return] => return_expr(p),
131 T![continue] => continue_expr(p), 127 T![continue] => continue_expr(p),
@@ -261,6 +257,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
261// if true {} else {}; 257// if true {} else {};
262// if true {} else if false {} else {}; 258// if true {} else if false {} else {};
263// if S {}; 259// if S {};
260// if { true } { } else { };
264// } 261// }
265fn if_expr(p: &mut Parser) -> CompletedMarker { 262fn if_expr(p: &mut Parser) -> CompletedMarker {
266 assert!(p.at(T![if])); 263 assert!(p.at(T![if]));
@@ -309,6 +306,7 @@ fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
309// fn foo() { 306// fn foo() {
310// while true {}; 307// while true {};
311// while let Some(x) = it.next() {}; 308// while let Some(x) = it.next() {};
309// while { true } {};
312// } 310// }
313fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { 311fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
314 assert!(p.at(T![while])); 312 assert!(p.at(T![while]));
@@ -356,6 +354,8 @@ fn cond(p: &mut Parser) {
356// fn foo() { 354// fn foo() {
357// match () { }; 355// match () { };
358// match S {}; 356// match S {};
357// match { } { _ => () };
358// match { S {} } {};
359// } 359// }
360fn match_expr(p: &mut Parser) -> CompletedMarker { 360fn match_expr(p: &mut Parser) -> CompletedMarker {
361 assert!(p.at(T![match])); 361 assert!(p.at(T![match]));
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 30328f59f..17477a696 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -1,5 +1,5 @@
1// Stores definitions which must be used in multiple places 1// Stores definitions which must be used in multiple places
2// See `cargo gen-syntax` (defined in crates/tools/src/main.rs) 2// See `cargo gen-syntax` (defined in crates/ra_tools/src/main.rs)
3Grammar( 3Grammar(
4 punct: [ 4 punct: [
5 (";", "SEMI"), 5 (";", "SEMI"),
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs
index 293046a04..2f8188160 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs
@@ -1,4 +1,5 @@
1fn foo() { 1fn foo() {
2 while true {}; 2 while true {};
3 while let Some(x) = it.next() {}; 3 while let Some(x) = it.next() {};
4 while { true } {};
4} 5}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt
index 9b43d624c..a6e14a114 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 70) 1SOURCE_FILE@[0; 93)
2 FN_DEF@[0; 69) 2 FN_DEF@[0; 92)
3 FN_KW@[0; 2) "fn" 3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " " 4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,8 +8,8 @@ SOURCE_FILE@[0; 70)
8 L_PAREN@[6; 7) "(" 8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")" 9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " " 10 WHITESPACE@[8; 9) " "
11 BLOCK_EXPR@[9; 69) 11 BLOCK_EXPR@[9; 92)
12 BLOCK@[9; 69) 12 BLOCK@[9; 92)
13 L_CURLY@[9; 10) "{" 13 L_CURLY@[9; 10) "{"
14 WHITESPACE@[10; 15) "\n " 14 WHITESPACE@[10; 15) "\n "
15 EXPR_STMT@[15; 29) 15 EXPR_STMT@[15; 29)
@@ -64,6 +64,26 @@ SOURCE_FILE@[0; 70)
64 L_CURLY@[64; 65) "{" 64 L_CURLY@[64; 65) "{"
65 R_CURLY@[65; 66) "}" 65 R_CURLY@[65; 66) "}"
66 SEMI@[66; 67) ";" 66 SEMI@[66; 67) ";"
67 WHITESPACE@[67; 68) "\n" 67 WHITESPACE@[67; 72) "\n "
68 R_CURLY@[68; 69) "}" 68 EXPR_STMT@[72; 90)
69 WHITESPACE@[69; 70) "\n" 69 WHILE_EXPR@[72; 89)
70 WHILE_KW@[72; 77) "while"
71 WHITESPACE@[77; 78) " "
72 CONDITION@[78; 86)
73 BLOCK_EXPR@[78; 86)
74 BLOCK@[78; 86)
75 L_CURLY@[78; 79) "{"
76 WHITESPACE@[79; 80) " "
77 LITERAL@[80; 84)
78 TRUE_KW@[80; 84) "true"
79 WHITESPACE@[84; 85) " "
80 R_CURLY@[85; 86) "}"
81 WHITESPACE@[86; 87) " "
82 BLOCK_EXPR@[87; 89)
83 BLOCK@[87; 89)
84 L_CURLY@[87; 88) "{"
85 R_CURLY@[88; 89) "}"
86 SEMI@[89; 90) ";"
87 WHITESPACE@[90; 91) "\n"
88 R_CURLY@[91; 92) "}"
89 WHITESPACE@[92; 93) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs
index 4b0d9af89..40f227ba3 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs
@@ -3,4 +3,5 @@ fn foo() {
3 if true {} else {}; 3 if true {} else {};
4 if true {} else if false {} else {}; 4 if true {} else if false {} else {};
5 if S {}; 5 if S {};
6 if { true } { } else { };
6} 7}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt
index 14ea91fd2..2ace3c8ee 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 107) 1SOURCE_FILE@[0; 137)
2 FN_DEF@[0; 106) 2 FN_DEF@[0; 136)
3 FN_KW@[0; 2) "fn" 3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " " 4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,8 +8,8 @@ SOURCE_FILE@[0; 107)
8 L_PAREN@[6; 7) "(" 8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")" 9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " " 10 WHITESPACE@[8; 9) " "
11 BLOCK_EXPR@[9; 106) 11 BLOCK_EXPR@[9; 136)
12 BLOCK@[9; 106) 12 BLOCK@[9; 136)
13 L_CURLY@[9; 10) "{" 13 L_CURLY@[9; 10) "{"
14 WHITESPACE@[10; 15) "\n " 14 WHITESPACE@[10; 15) "\n "
15 EXPR_STMT@[15; 26) 15 EXPR_STMT@[15; 26)
@@ -98,6 +98,35 @@ SOURCE_FILE@[0; 107)
98 L_CURLY@[101; 102) "{" 98 L_CURLY@[101; 102) "{"
99 R_CURLY@[102; 103) "}" 99 R_CURLY@[102; 103) "}"
100 SEMI@[103; 104) ";" 100 SEMI@[103; 104) ";"
101 WHITESPACE@[104; 105) "\n" 101 WHITESPACE@[104; 109) "\n "
102 R_CURLY@[105; 106) "}" 102 EXPR_STMT@[109; 134)
103 WHITESPACE@[106; 107) "\n" 103 IF_EXPR@[109; 133)
104 IF_KW@[109; 111) "if"
105 WHITESPACE@[111; 112) " "
106 CONDITION@[112; 120)
107 BLOCK_EXPR@[112; 120)
108 BLOCK@[112; 120)
109 L_CURLY@[112; 113) "{"
110 WHITESPACE@[113; 114) " "
111 LITERAL@[114; 118)
112 TRUE_KW@[114; 118) "true"
113 WHITESPACE@[118; 119) " "
114 R_CURLY@[119; 120) "}"
115 WHITESPACE@[120; 121) " "
116 BLOCK_EXPR@[121; 124)
117 BLOCK@[121; 124)
118 L_CURLY@[121; 122) "{"
119 WHITESPACE@[122; 123) " "
120 R_CURLY@[123; 124) "}"
121 WHITESPACE@[124; 125) " "
122 ELSE_KW@[125; 129) "else"
123 WHITESPACE@[129; 130) " "
124 BLOCK_EXPR@[130; 133)
125 BLOCK@[130; 133)
126 L_CURLY@[130; 131) "{"
127 WHITESPACE@[131; 132) " "
128 R_CURLY@[132; 133) "}"
129 SEMI@[133; 134) ";"
130 WHITESPACE@[134; 135) "\n"
131 R_CURLY@[135; 136) "}"
132 WHITESPACE@[136; 137) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs
index c9205dfa3..c4021dc10 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs
@@ -1,4 +1,6 @@
1fn foo() { 1fn foo() {
2 match () { }; 2 match () { };
3 match S {}; 3 match S {};
4 match { } { _ => () };
5 match { S {} } {};
4} 6}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt
index f62b6c6d5..0af668056 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 47) 1SOURCE_FILE@[0; 97)
2 FN_DEF@[0; 46) 2 FN_DEF@[0; 96)
3 FN_KW@[0; 2) "fn" 3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " " 4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,8 +8,8 @@ SOURCE_FILE@[0; 47)
8 L_PAREN@[6; 7) "(" 8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")" 9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " " 10 WHITESPACE@[8; 9) " "
11 BLOCK_EXPR@[9; 46) 11 BLOCK_EXPR@[9; 96)
12 BLOCK@[9; 46) 12 BLOCK@[9; 96)
13 L_CURLY@[9; 10) "{" 13 L_CURLY@[9; 10) "{"
14 WHITESPACE@[10; 15) "\n " 14 WHITESPACE@[10; 15) "\n "
15 EXPR_STMT@[15; 28) 15 EXPR_STMT@[15; 28)
@@ -40,6 +40,57 @@ SOURCE_FILE@[0; 47)
40 L_CURLY@[41; 42) "{" 40 L_CURLY@[41; 42) "{"
41 R_CURLY@[42; 43) "}" 41 R_CURLY@[42; 43) "}"
42 SEMI@[43; 44) ";" 42 SEMI@[43; 44) ";"
43 WHITESPACE@[44; 45) "\n" 43 WHITESPACE@[44; 49) "\n "
44 R_CURLY@[45; 46) "}" 44 EXPR_STMT@[49; 71)
45 WHITESPACE@[46; 47) "\n" 45 MATCH_EXPR@[49; 70)
46 MATCH_KW@[49; 54) "match"
47 WHITESPACE@[54; 55) " "
48 BLOCK_EXPR@[55; 58)
49 BLOCK@[55; 58)
50 L_CURLY@[55; 56) "{"
51 WHITESPACE@[56; 57) " "
52 R_CURLY@[57; 58) "}"
53 WHITESPACE@[58; 59) " "
54 MATCH_ARM_LIST@[59; 70)
55 L_CURLY@[59; 60) "{"
56 WHITESPACE@[60; 61) " "
57 MATCH_ARM@[61; 68)
58 PLACEHOLDER_PAT@[61; 62)
59 UNDERSCORE@[61; 62) "_"
60 WHITESPACE@[62; 63) " "
61 FAT_ARROW@[63; 65) "=>"
62 WHITESPACE@[65; 66) " "
63 TUPLE_EXPR@[66; 68)
64 L_PAREN@[66; 67) "("
65 R_PAREN@[67; 68) ")"
66 WHITESPACE@[68; 69) " "
67 R_CURLY@[69; 70) "}"
68 SEMI@[70; 71) ";"
69 WHITESPACE@[71; 76) "\n "
70 EXPR_STMT@[76; 94)
71 MATCH_EXPR@[76; 93)
72 MATCH_KW@[76; 81) "match"
73 WHITESPACE@[81; 82) " "
74 BLOCK_EXPR@[82; 90)
75 BLOCK@[82; 90)
76 L_CURLY@[82; 83) "{"
77 WHITESPACE@[83; 84) " "
78 RECORD_LIT@[84; 88)
79 PATH@[84; 85)
80 PATH_SEGMENT@[84; 85)
81 NAME_REF@[84; 85)
82 IDENT@[84; 85) "S"
83 WHITESPACE@[85; 86) " "
84 RECORD_FIELD_LIST@[86; 88)
85 L_CURLY@[86; 87) "{"
86 R_CURLY@[87; 88) "}"
87 WHITESPACE@[88; 89) " "
88 R_CURLY@[89; 90) "}"
89 WHITESPACE@[90; 91) " "
90 MATCH_ARM_LIST@[91; 93)
91 L_CURLY@[91; 92) "{"
92 R_CURLY@[92; 93) "}"
93 SEMI@[93; 94) ";"
94 WHITESPACE@[94; 95) "\n"
95 R_CURLY@[95; 96) "}"
96 WHITESPACE@[96; 97) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs
index c39fe8e68..e7b7cfc6b 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs
@@ -1 +1,5 @@
1fn foo() { let x = 1..; } 1fn foo() {
2 let x = 1..;
3 match 1.. { _ => () };
4 match a.b()..S { _ => () };
5}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt
index f3c292f5e..9f8a6b0f6 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 26) 1SOURCE_FILE@[0; 89)
2 FN_DEF@[0; 25) 2 FN_DEF@[0; 88)
3 FN_KW@[0; 2) "fn" 3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " " 4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,24 +8,89 @@ SOURCE_FILE@[0; 26)
8 L_PAREN@[6; 7) "(" 8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")" 9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " " 10 WHITESPACE@[8; 9) " "
11 BLOCK_EXPR@[9; 25) 11 BLOCK_EXPR@[9; 88)
12 BLOCK@[9; 25) 12 BLOCK@[9; 88)
13 L_CURLY@[9; 10) "{" 13 L_CURLY@[9; 10) "{"
14 WHITESPACE@[10; 11) " " 14 WHITESPACE@[10; 15) "\n "
15 LET_STMT@[11; 23) 15 LET_STMT@[15; 27)
16 LET_KW@[11; 14) "let" 16 LET_KW@[15; 18) "let"
17 WHITESPACE@[14; 15) " "
18 BIND_PAT@[15; 16)
19 NAME@[15; 16)
20 IDENT@[15; 16) "x"
21 WHITESPACE@[16; 17) " "
22 EQ@[17; 18) "="
23 WHITESPACE@[18; 19) " " 17 WHITESPACE@[18; 19) " "
24 RANGE_EXPR@[19; 22) 18 BIND_PAT@[19; 20)
25 LITERAL@[19; 20) 19 NAME@[19; 20)
26 INT_NUMBER@[19; 20) "1" 20 IDENT@[19; 20) "x"
27 DOTDOT@[20; 22) ".." 21 WHITESPACE@[20; 21) " "
28 SEMI@[22; 23) ";" 22 EQ@[21; 22) "="
29 WHITESPACE@[23; 24) " " 23 WHITESPACE@[22; 23) " "
30 R_CURLY@[24; 25) "}" 24 RANGE_EXPR@[23; 26)
31 WHITESPACE@[25; 26) "\n" 25 LITERAL@[23; 24)
26 INT_NUMBER@[23; 24) "1"
27 DOTDOT@[24; 26) ".."
28 SEMI@[26; 27) ";"
29 WHITESPACE@[27; 32) "\n "
30 EXPR_STMT@[32; 54)
31 MATCH_EXPR@[32; 53)
32 MATCH_KW@[32; 37) "match"
33 WHITESPACE@[37; 38) " "
34 RANGE_EXPR@[38; 41)
35 LITERAL@[38; 39)
36 INT_NUMBER@[38; 39) "1"
37 DOTDOT@[39; 41) ".."
38 WHITESPACE@[41; 42) " "
39 MATCH_ARM_LIST@[42; 53)
40 L_CURLY@[42; 43) "{"
41 WHITESPACE@[43; 44) " "
42 MATCH_ARM@[44; 51)
43 PLACEHOLDER_PAT@[44; 45)
44 UNDERSCORE@[44; 45) "_"
45 WHITESPACE@[45; 46) " "
46 FAT_ARROW@[46; 48) "=>"
47 WHITESPACE@[48; 49) " "
48 TUPLE_EXPR@[49; 51)
49 L_PAREN@[49; 50) "("
50 R_PAREN@[50; 51) ")"
51 WHITESPACE@[51; 52) " "
52 R_CURLY@[52; 53) "}"
53 SEMI@[53; 54) ";"
54 WHITESPACE@[54; 59) "\n "
55 EXPR_STMT@[59; 86)
56 MATCH_EXPR@[59; 85)
57 MATCH_KW@[59; 64) "match"
58 WHITESPACE@[64; 65) " "
59 RANGE_EXPR@[65; 73)
60 METHOD_CALL_EXPR@[65; 70)
61 PATH_EXPR@[65; 66)
62 PATH@[65; 66)
63 PATH_SEGMENT@[65; 66)
64 NAME_REF@[65; 66)
65 IDENT@[65; 66) "a"
66 DOT@[66; 67) "."
67 NAME_REF@[67; 68)
68 IDENT@[67; 68) "b"
69 ARG_LIST@[68; 70)
70 L_PAREN@[68; 69) "("
71 R_PAREN@[69; 70) ")"
72 DOTDOT@[70; 72) ".."
73 PATH_EXPR@[72; 73)
74 PATH@[72; 73)
75 PATH_SEGMENT@[72; 73)
76 NAME_REF@[72; 73)
77 IDENT@[72; 73) "S"
78 WHITESPACE@[73; 74) " "
79 MATCH_ARM_LIST@[74; 85)
80 L_CURLY@[74; 75) "{"
81 WHITESPACE@[75; 76) " "
82 MATCH_ARM@[76; 83)
83 PLACEHOLDER_PAT@[76; 77)
84 UNDERSCORE@[76; 77) "_"
85 WHITESPACE@[77; 78) " "
86 FAT_ARROW@[78; 80) "=>"
87 WHITESPACE@[80; 81) " "
88 TUPLE_EXPR@[81; 83)
89 L_PAREN@[81; 82) "("
90 R_PAREN@[82; 83) ")"
91 WHITESPACE@[83; 84) " "
92 R_CURLY@[84; 85) "}"
93 SEMI@[85; 86) ";"
94 WHITESPACE@[86; 87) "\n"
95 R_CURLY@[87; 88) "}"
96 WHITESPACE@[88; 89) "\n"