diff options
-rw-r--r-- | src/grammar.ron | 1 | ||||
-rw-r--r-- | src/grammar/expressions/atom.rs | 4 | ||||
-rw-r--r-- | src/grammar/expressions/mod.rs | 47 | ||||
-rw-r--r-- | src/grammar/patterns.rs | 23 | ||||
-rw-r--r-- | src/syntax_kinds/generated.rs | 2 | ||||
-rw-r--r-- | tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.rs | 7 | ||||
-rw-r--r-- | tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.txt | 58 | ||||
-rw-r--r-- | tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.rs | 4 | ||||
-rw-r--r-- | tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.txt | 50 | ||||
-rw-r--r-- | tests/data/parser/inline/0089_slice_pat.rs | 3 | ||||
-rw-r--r-- | tests/data/parser/inline/0089_slice_pat.txt | 40 |
11 files changed, 224 insertions, 15 deletions
diff --git a/src/grammar.ron b/src/grammar.ron index 960838c97..f1c3502bc 100644 --- a/src/grammar.ron +++ b/src/grammar.ron | |||
@@ -142,6 +142,7 @@ Grammar( | |||
142 | "STRUCT_PAT", | 142 | "STRUCT_PAT", |
143 | "TUPLE_STRUCT_PAT", | 143 | "TUPLE_STRUCT_PAT", |
144 | "TUPLE_PAT", | 144 | "TUPLE_PAT", |
145 | "SLICE_PAT", | ||
145 | 146 | ||
146 | // atoms | 147 | // atoms |
147 | "TUPLE_EXPR", | 148 | "TUPLE_EXPR", |
diff --git a/src/grammar/expressions/atom.rs b/src/grammar/expressions/atom.rs index 524a69a8c..af9f47c5e 100644 --- a/src/grammar/expressions/atom.rs +++ b/src/grammar/expressions/atom.rs | |||
@@ -262,7 +262,7 @@ fn match_arm(p: &mut Parser) -> BlockLike { | |||
262 | expr_no_struct(p); | 262 | expr_no_struct(p); |
263 | } | 263 | } |
264 | p.expect(FAT_ARROW); | 264 | p.expect(FAT_ARROW); |
265 | let ret = expr(p); | 265 | let ret = expr_stmt(p); |
266 | m.complete(p, MATCH_ARM); | 266 | m.complete(p, MATCH_ARM); |
267 | ret | 267 | ret |
268 | } | 268 | } |
@@ -295,7 +295,7 @@ pub(super) fn block_expr(p: &mut Parser) -> CompletedMarker { | |||
295 | // test pub_expr | 295 | // test pub_expr |
296 | // fn foo() { pub 92; } //FIXME | 296 | // fn foo() { pub 92; } //FIXME |
297 | items::MaybeItem::None => { | 297 | items::MaybeItem::None => { |
298 | let is_blocklike = expressions::expr(p) == BlockLike::Block; | 298 | let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block; |
299 | if p.eat(SEMI) || (is_blocklike && !p.at(R_CURLY)) { | 299 | if p.eat(SEMI) || (is_blocklike && !p.at(R_CURLY)) { |
300 | m.complete(p, EXPR_STMT); | 300 | m.complete(p, EXPR_STMT); |
301 | } else { | 301 | } else { |
diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs index ce709dbb2..dcbb1e2a8 100644 --- a/src/grammar/expressions/mod.rs +++ b/src/grammar/expressions/mod.rs | |||
@@ -6,12 +6,17 @@ pub(super) use self::atom::literal; | |||
6 | const EXPR_FIRST: TokenSet = LHS_FIRST; | 6 | const EXPR_FIRST: TokenSet = LHS_FIRST; |
7 | 7 | ||
8 | pub(super) fn expr(p: &mut Parser) -> BlockLike { | 8 | pub(super) fn expr(p: &mut Parser) -> BlockLike { |
9 | let r = Restrictions { forbid_structs: false }; | 9 | let r = Restrictions { forbid_structs: false, prefer_stmt: false }; |
10 | expr_bp(p, r, 1) | ||
11 | } | ||
12 | |||
13 | pub(super) fn expr_stmt(p: &mut Parser) -> BlockLike { | ||
14 | let r = Restrictions { forbid_structs: false, prefer_stmt: true }; | ||
10 | expr_bp(p, r, 1) | 15 | expr_bp(p, r, 1) |
11 | } | 16 | } |
12 | 17 | ||
13 | fn expr_no_struct(p: &mut Parser) { | 18 | fn expr_no_struct(p: &mut Parser) { |
14 | let r = Restrictions { forbid_structs: true }; | 19 | let r = Restrictions { forbid_structs: true, prefer_stmt: false }; |
15 | expr_bp(p, r, 1); | 20 | expr_bp(p, r, 1); |
16 | } | 21 | } |
17 | 22 | ||
@@ -30,7 +35,8 @@ pub(super) fn block(p: &mut Parser) { | |||
30 | 35 | ||
31 | #[derive(Clone, Copy)] | 36 | #[derive(Clone, Copy)] |
32 | struct Restrictions { | 37 | struct Restrictions { |
33 | forbid_structs: bool | 38 | forbid_structs: bool, |
39 | prefer_stmt: bool, | ||
34 | } | 40 | } |
35 | 41 | ||
36 | enum Op { | 42 | enum Op { |
@@ -86,12 +92,18 @@ fn current_op(p: &Parser) -> (u8, Op) { | |||
86 | 92 | ||
87 | // Parses expression with binding power of at least bp. | 93 | // Parses expression with binding power of at least bp. |
88 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { | 94 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { |
89 | let mut block: bool; | ||
90 | let mut lhs = match lhs(p, r) { | 95 | let mut lhs = match lhs(p, r) { |
91 | Some(lhs) => { | 96 | Some(lhs) => { |
92 | block = is_block(lhs.kind()); | 97 | // test stmt_bin_expr_ambiguity |
98 | // fn foo() { | ||
99 | // let _ = {1} & 2; | ||
100 | // {1} &2; | ||
101 | // } | ||
102 | if r.prefer_stmt && is_block(lhs.kind()) { | ||
103 | return BlockLike::Block; | ||
104 | } | ||
93 | lhs | 105 | lhs |
94 | }, | 106 | } |
95 | None => return BlockLike::NotBlock, | 107 | None => return BlockLike::NotBlock, |
96 | }; | 108 | }; |
97 | 109 | ||
@@ -101,7 +113,6 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { | |||
101 | if op_bp < bp { | 113 | if op_bp < bp { |
102 | break; | 114 | break; |
103 | } | 115 | } |
104 | block = false; | ||
105 | let m = lhs.precede(p); | 116 | let m = lhs.precede(p); |
106 | match op { | 117 | match op { |
107 | Op::Simple => p.bump(), | 118 | Op::Simple => p.bump(), |
@@ -112,7 +123,7 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { | |||
112 | expr_bp(p, r, op_bp + 1); | 123 | expr_bp(p, r, op_bp + 1); |
113 | lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); | 124 | lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); |
114 | } | 125 | } |
115 | if block { BlockLike::Block } else { BlockLike::NotBlock } | 126 | BlockLike::NotBlock |
116 | } | 127 | } |
117 | 128 | ||
118 | // test no_semi_after_block | 129 | // test no_semi_after_block |
@@ -171,18 +182,27 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { | |||
171 | } | 182 | } |
172 | _ => { | 183 | _ => { |
173 | let lhs = atom::atom_expr(p, r)?; | 184 | let lhs = atom::atom_expr(p, r)?; |
174 | return Some(postfix_expr(p, lhs)); | 185 | return Some(postfix_expr(p, r, lhs)); |
175 | } | 186 | } |
176 | }; | 187 | }; |
177 | expr_bp(p, r, 255); | 188 | expr_bp(p, r, 255); |
178 | Some(m.complete(p, kind)) | 189 | Some(m.complete(p, kind)) |
179 | } | 190 | } |
180 | 191 | ||
181 | fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { | 192 | fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker { |
193 | let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind()); | ||
182 | loop { | 194 | loop { |
183 | lhs = match p.current() { | 195 | lhs = match p.current() { |
184 | L_PAREN => call_expr(p, lhs), | 196 | // test stmt_postfix_expr_ambiguity |
185 | L_BRACK => index_expr(p, lhs), | 197 | // fn foo() { |
198 | // match () { | ||
199 | // _ => {} | ||
200 | // () => {} | ||
201 | // [] => {} | ||
202 | // } | ||
203 | // } | ||
204 | L_PAREN if allow_calls => call_expr(p, lhs), | ||
205 | L_BRACK if allow_calls => index_expr(p, lhs), | ||
186 | DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON { | 206 | DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON { |
187 | method_call_expr(p, lhs) | 207 | method_call_expr(p, lhs) |
188 | } else { | 208 | } else { |
@@ -199,7 +219,8 @@ fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { | |||
199 | QUESTION => try_expr(p, lhs), | 219 | QUESTION => try_expr(p, lhs), |
200 | AS_KW => cast_expr(p, lhs), | 220 | AS_KW => cast_expr(p, lhs), |
201 | _ => break, | 221 | _ => break, |
202 | } | 222 | }; |
223 | allow_calls = true | ||
203 | } | 224 | } |
204 | lhs | 225 | lhs |
205 | } | 226 | } |
diff --git a/src/grammar/patterns.rs b/src/grammar/patterns.rs index f1d48b5fa..36ead7561 100644 --- a/src/grammar/patterns.rs +++ b/src/grammar/patterns.rs | |||
@@ -17,6 +17,7 @@ pub(super) fn pattern(p: &mut Parser) { | |||
17 | UNDERSCORE => placeholder_pat(p), | 17 | UNDERSCORE => placeholder_pat(p), |
18 | AMP => ref_pat(p), | 18 | AMP => ref_pat(p), |
19 | L_PAREN => tuple_pat(p), | 19 | L_PAREN => tuple_pat(p), |
20 | L_BRACK => slice_pat(p), | ||
20 | _ => p.err_and_bump("expected pattern"), | 21 | _ => p.err_and_bump("expected pattern"), |
21 | } | 22 | } |
22 | } | 23 | } |
@@ -128,6 +129,28 @@ fn tuple_pat(p: &mut Parser) { | |||
128 | m.complete(p, TUPLE_PAT); | 129 | m.complete(p, TUPLE_PAT); |
129 | } | 130 | } |
130 | 131 | ||
132 | // test slice_pat | ||
133 | // fn main() { | ||
134 | // let [a, b, ..] = []; | ||
135 | // } | ||
136 | fn slice_pat(p: &mut Parser) { | ||
137 | assert!(p.at(L_BRACK)); | ||
138 | let m = p.start(); | ||
139 | p.bump(); | ||
140 | while !p.at(EOF) && !p.at(R_BRACK) { | ||
141 | match p.current() { | ||
142 | DOTDOT => p.bump(), | ||
143 | _ => pattern(p), | ||
144 | } | ||
145 | if !p.at(R_BRACK) { | ||
146 | p.expect(COMMA); | ||
147 | } | ||
148 | } | ||
149 | p.expect(R_BRACK); | ||
150 | |||
151 | m.complete(p, SLICE_PAT); | ||
152 | } | ||
153 | |||
131 | // test bind_pat | 154 | // test bind_pat |
132 | // fn main() { | 155 | // fn main() { |
133 | // let a = (); | 156 | // let a = (); |
diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index cf286a0f1..0c6a1f8e7 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs | |||
@@ -134,6 +134,7 @@ pub enum SyntaxKind { | |||
134 | STRUCT_PAT, | 134 | STRUCT_PAT, |
135 | TUPLE_STRUCT_PAT, | 135 | TUPLE_STRUCT_PAT, |
136 | TUPLE_PAT, | 136 | TUPLE_PAT, |
137 | SLICE_PAT, | ||
137 | TUPLE_EXPR, | 138 | TUPLE_EXPR, |
138 | ARRAY_EXPR, | 139 | ARRAY_EXPR, |
139 | PAREN_EXPR, | 140 | PAREN_EXPR, |
@@ -372,6 +373,7 @@ impl SyntaxKind { | |||
372 | STRUCT_PAT => &SyntaxInfo { name: "STRUCT_PAT" }, | 373 | STRUCT_PAT => &SyntaxInfo { name: "STRUCT_PAT" }, |
373 | TUPLE_STRUCT_PAT => &SyntaxInfo { name: "TUPLE_STRUCT_PAT" }, | 374 | TUPLE_STRUCT_PAT => &SyntaxInfo { name: "TUPLE_STRUCT_PAT" }, |
374 | TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" }, | 375 | TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" }, |
376 | SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" }, | ||
375 | TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" }, | 377 | TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" }, |
376 | ARRAY_EXPR => &SyntaxInfo { name: "ARRAY_EXPR" }, | 378 | ARRAY_EXPR => &SyntaxInfo { name: "ARRAY_EXPR" }, |
377 | PAREN_EXPR => &SyntaxInfo { name: "PAREN_EXPR" }, | 379 | PAREN_EXPR => &SyntaxInfo { name: "PAREN_EXPR" }, |
diff --git a/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.rs b/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.rs new file mode 100644 index 000000000..2edd578f9 --- /dev/null +++ b/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.rs | |||
@@ -0,0 +1,7 @@ | |||
1 | fn foo() { | ||
2 | match () { | ||
3 | _ => {} | ||
4 | () => {} | ||
5 | [] => {} | ||
6 | } | ||
7 | } | ||
diff --git a/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.txt b/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.txt new file mode 100644 index 000000000..47b4d4481 --- /dev/null +++ b/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.txt | |||
@@ -0,0 +1,58 @@ | |||
1 | FILE@[0; 84) | ||
2 | FN_ITEM@[0; 83) | ||
3 | FN_KW@[0; 2) | ||
4 | WHITESPACE@[2; 3) | ||
5 | NAME@[3; 6) | ||
6 | IDENT@[3; 6) "foo" | ||
7 | PARAM_LIST@[6; 8) | ||
8 | L_PAREN@[6; 7) | ||
9 | R_PAREN@[7; 8) | ||
10 | WHITESPACE@[8; 9) | ||
11 | BLOCK_EXPR@[9; 83) | ||
12 | L_CURLY@[9; 10) | ||
13 | WHITESPACE@[10; 15) | ||
14 | MATCH_EXPR@[15; 81) | ||
15 | MATCH_KW@[15; 20) | ||
16 | WHITESPACE@[20; 21) | ||
17 | TUPLE_EXPR@[21; 23) | ||
18 | L_PAREN@[21; 22) | ||
19 | R_PAREN@[22; 23) | ||
20 | WHITESPACE@[23; 24) | ||
21 | L_CURLY@[24; 25) | ||
22 | WHITESPACE@[25; 34) | ||
23 | MATCH_ARM@[34; 41) | ||
24 | PLACEHOLDER_PAT@[34; 35) | ||
25 | UNDERSCORE@[34; 35) | ||
26 | WHITESPACE@[35; 36) | ||
27 | FAT_ARROW@[36; 38) | ||
28 | WHITESPACE@[38; 39) | ||
29 | BLOCK_EXPR@[39; 41) | ||
30 | L_CURLY@[39; 40) | ||
31 | R_CURLY@[40; 41) | ||
32 | WHITESPACE@[41; 50) | ||
33 | MATCH_ARM@[50; 58) | ||
34 | TUPLE_PAT@[50; 52) | ||
35 | L_PAREN@[50; 51) | ||
36 | R_PAREN@[51; 52) | ||
37 | WHITESPACE@[52; 53) | ||
38 | FAT_ARROW@[53; 55) | ||
39 | WHITESPACE@[55; 56) | ||
40 | BLOCK_EXPR@[56; 58) | ||
41 | L_CURLY@[56; 57) | ||
42 | R_CURLY@[57; 58) | ||
43 | WHITESPACE@[58; 67) | ||
44 | MATCH_ARM@[67; 75) | ||
45 | SLICE_PAT@[67; 69) | ||
46 | L_BRACK@[67; 68) | ||
47 | R_BRACK@[68; 69) | ||
48 | WHITESPACE@[69; 70) | ||
49 | FAT_ARROW@[70; 72) | ||
50 | WHITESPACE@[72; 73) | ||
51 | BLOCK_EXPR@[73; 75) | ||
52 | L_CURLY@[73; 74) | ||
53 | R_CURLY@[74; 75) | ||
54 | WHITESPACE@[75; 80) | ||
55 | R_CURLY@[80; 81) | ||
56 | WHITESPACE@[81; 82) | ||
57 | R_CURLY@[82; 83) | ||
58 | WHITESPACE@[83; 84) | ||
diff --git a/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.rs b/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.rs new file mode 100644 index 000000000..37b843742 --- /dev/null +++ b/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.rs | |||
@@ -0,0 +1,4 @@ | |||
1 | fn foo() { | ||
2 | let _ = {1} & 2; | ||
3 | {1} &2; | ||
4 | } | ||
diff --git a/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.txt b/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.txt new file mode 100644 index 000000000..df0aa44b3 --- /dev/null +++ b/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.txt | |||
@@ -0,0 +1,50 @@ | |||
1 | FILE@[0; 46) | ||
2 | FN_ITEM@[0; 45) | ||
3 | FN_KW@[0; 2) | ||
4 | WHITESPACE@[2; 3) | ||
5 | NAME@[3; 6) | ||
6 | IDENT@[3; 6) "foo" | ||
7 | PARAM_LIST@[6; 8) | ||
8 | L_PAREN@[6; 7) | ||
9 | R_PAREN@[7; 8) | ||
10 | WHITESPACE@[8; 9) | ||
11 | BLOCK_EXPR@[9; 45) | ||
12 | L_CURLY@[9; 10) | ||
13 | WHITESPACE@[10; 15) | ||
14 | LET_STMT@[15; 31) | ||
15 | LET_KW@[15; 18) | ||
16 | WHITESPACE@[18; 19) | ||
17 | PLACEHOLDER_PAT@[19; 20) | ||
18 | UNDERSCORE@[19; 20) | ||
19 | WHITESPACE@[20; 21) | ||
20 | EQ@[21; 22) | ||
21 | WHITESPACE@[22; 23) | ||
22 | BIN_EXPR@[23; 30) | ||
23 | BLOCK_EXPR@[23; 26) | ||
24 | L_CURLY@[23; 24) | ||
25 | LITERAL@[24; 25) | ||
26 | INT_NUMBER@[24; 25) "1" | ||
27 | R_CURLY@[25; 26) | ||
28 | WHITESPACE@[26; 27) | ||
29 | AMP@[27; 28) | ||
30 | WHITESPACE@[28; 29) | ||
31 | LITERAL@[29; 30) | ||
32 | INT_NUMBER@[29; 30) "2" | ||
33 | SEMI@[30; 31) | ||
34 | WHITESPACE@[31; 36) | ||
35 | EXPR_STMT@[36; 39) | ||
36 | BLOCK_EXPR@[36; 39) | ||
37 | L_CURLY@[36; 37) | ||
38 | LITERAL@[37; 38) | ||
39 | INT_NUMBER@[37; 38) "1" | ||
40 | R_CURLY@[38; 39) | ||
41 | WHITESPACE@[39; 40) | ||
42 | EXPR_STMT@[40; 43) | ||
43 | REF_EXPR@[40; 42) | ||
44 | AMP@[40; 41) | ||
45 | LITERAL@[41; 42) | ||
46 | INT_NUMBER@[41; 42) "2" | ||
47 | SEMI@[42; 43) | ||
48 | WHITESPACE@[43; 44) | ||
49 | R_CURLY@[44; 45) | ||
50 | WHITESPACE@[45; 46) | ||
diff --git a/tests/data/parser/inline/0089_slice_pat.rs b/tests/data/parser/inline/0089_slice_pat.rs new file mode 100644 index 000000000..7955973b9 --- /dev/null +++ b/tests/data/parser/inline/0089_slice_pat.rs | |||
@@ -0,0 +1,3 @@ | |||
1 | fn main() { | ||
2 | let [a, b, ..] = []; | ||
3 | } | ||
diff --git a/tests/data/parser/inline/0089_slice_pat.txt b/tests/data/parser/inline/0089_slice_pat.txt new file mode 100644 index 000000000..1e7f20119 --- /dev/null +++ b/tests/data/parser/inline/0089_slice_pat.txt | |||
@@ -0,0 +1,40 @@ | |||
1 | FILE@[0; 39) | ||
2 | FN_ITEM@[0; 38) | ||
3 | FN_KW@[0; 2) | ||
4 | WHITESPACE@[2; 3) | ||
5 | NAME@[3; 7) | ||
6 | IDENT@[3; 7) "main" | ||
7 | PARAM_LIST@[7; 9) | ||
8 | L_PAREN@[7; 8) | ||
9 | R_PAREN@[8; 9) | ||
10 | WHITESPACE@[9; 10) | ||
11 | BLOCK_EXPR@[10; 38) | ||
12 | L_CURLY@[10; 11) | ||
13 | WHITESPACE@[11; 16) | ||
14 | LET_STMT@[16; 36) | ||
15 | LET_KW@[16; 19) | ||
16 | WHITESPACE@[19; 20) | ||
17 | SLICE_PAT@[20; 30) | ||
18 | L_BRACK@[20; 21) | ||
19 | BIND_PAT@[21; 22) | ||
20 | NAME@[21; 22) | ||
21 | IDENT@[21; 22) "a" | ||
22 | COMMA@[22; 23) | ||
23 | WHITESPACE@[23; 24) | ||
24 | BIND_PAT@[24; 25) | ||
25 | NAME@[24; 25) | ||
26 | IDENT@[24; 25) "b" | ||
27 | COMMA@[25; 26) | ||
28 | WHITESPACE@[26; 27) | ||
29 | DOTDOT@[27; 29) | ||
30 | R_BRACK@[29; 30) | ||
31 | WHITESPACE@[30; 31) | ||
32 | EQ@[31; 32) | ||
33 | WHITESPACE@[32; 33) | ||
34 | ARRAY_EXPR@[33; 35) | ||
35 | L_BRACK@[33; 34) | ||
36 | R_BRACK@[34; 35) | ||
37 | SEMI@[35; 36) | ||
38 | WHITESPACE@[36; 37) | ||
39 | R_CURLY@[37; 38) | ||
40 | WHITESPACE@[38; 39) | ||