diff options
author | Aleksey Kladov <[email protected]> | 2018-08-05 16:07:06 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-05 16:07:06 +0100 |
commit | b0291cd8c2ec1d6d164caaa743f7484416e9b3f5 (patch) | |
tree | 57a2b21085bf0996d37c3f8d757f0332c5055a5a | |
parent | 80fa861cd688c8e7c92e27feaf6623ecfaa4901e (diff) |
Range expr
-rw-r--r-- | src/grammar.ron | 1 | ||||
-rw-r--r-- | src/grammar/expressions/mod.rs | 37 | ||||
-rw-r--r-- | src/syntax_kinds/generated.rs | 2 | ||||
-rw-r--r-- | tests/data/parser/inline/0082_range_binding_power.rs | 5 | ||||
-rw-r--r-- | tests/data/parser/inline/0082_range_binding_power.txt | 72 | ||||
-rw-r--r-- | tests/data/parser/inline/0083_postfix_range.rs | 1 | ||||
-rw-r--r-- | tests/data/parser/inline/0083_postfix_range.txt | 30 |
7 files changed, 140 insertions, 8 deletions
diff --git a/src/grammar.ron b/src/grammar.ron index 1eb76abdd..9e122091b 100644 --- a/src/grammar.ron +++ b/src/grammar.ron | |||
@@ -163,6 +163,7 @@ Grammar( | |||
163 | "DEREF_EXPR", | 163 | "DEREF_EXPR", |
164 | "NOT_EXPR", | 164 | "NOT_EXPR", |
165 | 165 | ||
166 | "RANGE_EXPR", // just weird | ||
166 | "BIN_EXPR", | 167 | "BIN_EXPR", |
167 | 168 | ||
168 | 169 | ||
diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs index 7f3bc78f2..0312a757a 100644 --- a/src/grammar/expressions/mod.rs +++ b/src/grammar/expressions/mod.rs | |||
@@ -44,6 +44,13 @@ enum Op { | |||
44 | // *x = 1 + 1; | 44 | // *x = 1 + 1; |
45 | // } | 45 | // } |
46 | 46 | ||
47 | // test range_binding_power | ||
48 | // fn foo() { | ||
49 | // .. 1 + 1; | ||
50 | // .. z = 2; | ||
51 | // x = false .. 1 == 1; | ||
52 | // } | ||
53 | |||
47 | // test compound_ops | 54 | // test compound_ops |
48 | // fn foo() { | 55 | // fn foo() { |
49 | // x += 1; | 56 | // x += 1; |
@@ -52,10 +59,10 @@ enum Op { | |||
52 | // } | 59 | // } |
53 | fn current_op(p: &Parser) -> (u8, Op) { | 60 | fn current_op(p: &Parser) -> (u8, Op) { |
54 | if p.at_compound2(L_ANGLE, EQ) { | 61 | if p.at_compound2(L_ANGLE, EQ) { |
55 | return (2, Op::Composite(LTEQ, 2)); | 62 | return (3, Op::Composite(LTEQ, 2)); |
56 | } | 63 | } |
57 | if p.at_compound2(R_ANGLE, EQ) { | 64 | if p.at_compound2(R_ANGLE, EQ) { |
58 | return (2, Op::Composite(GTEQ, 2)); | 65 | return (3, Op::Composite(GTEQ, 2)); |
59 | } | 66 | } |
60 | if p.at_compound2(PLUS, EQ) { | 67 | if p.at_compound2(PLUS, EQ) { |
61 | return (1, Op::Composite(PLUSEQ, 2)); | 68 | return (1, Op::Composite(PLUSEQ, 2)); |
@@ -66,9 +73,10 @@ fn current_op(p: &Parser) -> (u8, Op) { | |||
66 | 73 | ||
67 | let bp = match p.current() { | 74 | let bp = match p.current() { |
68 | EQ => 1, | 75 | EQ => 1, |
69 | EQEQ | NEQ => 2, | 76 | DOTDOT => 2, |
70 | MINUS | PLUS => 3, | 77 | EQEQ | NEQ => 3, |
71 | STAR | SLASH => 4, | 78 | MINUS | PLUS => 4, |
79 | STAR | SLASH => 5, | ||
72 | _ => 0, | 80 | _ => 0, |
73 | }; | 81 | }; |
74 | (bp, Op::Simple) | 82 | (bp, Op::Simple) |
@@ -76,7 +84,7 @@ fn current_op(p: &Parser) -> (u8, Op) { | |||
76 | 84 | ||
77 | // Parses expression with binding power of at least bp. | 85 | // Parses expression with binding power of at least bp. |
78 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { | 86 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { |
79 | let mut lhs = match unary_expr(p, r) { | 87 | let mut lhs = match lhs(p, r) { |
80 | Some(lhs) => lhs, | 88 | Some(lhs) => lhs, |
81 | None => return, | 89 | None => return, |
82 | }; | 90 | }; |
@@ -102,7 +110,7 @@ const UNARY_EXPR_FIRST: TokenSet = | |||
102 | atom::ATOM_EXPR_FIRST, | 110 | atom::ATOM_EXPR_FIRST, |
103 | ]; | 111 | ]; |
104 | 112 | ||
105 | fn unary_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { | 113 | fn lhs(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { |
106 | let m; | 114 | let m; |
107 | let kind = match p.current() { | 115 | let kind = match p.current() { |
108 | // test ref_expr | 116 | // test ref_expr |
@@ -134,12 +142,18 @@ fn unary_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { | |||
134 | p.bump(); | 142 | p.bump(); |
135 | NOT_EXPR | 143 | NOT_EXPR |
136 | } | 144 | } |
145 | DOTDOT => { | ||
146 | m = p.start(); | ||
147 | p.bump(); | ||
148 | expr_bp(p, r, 2); | ||
149 | return Some(m.complete(p, RANGE_EXPR)); | ||
150 | } | ||
137 | _ => { | 151 | _ => { |
138 | let lhs = atom::atom_expr(p, r)?; | 152 | let lhs = atom::atom_expr(p, r)?; |
139 | return Some(postfix_expr(p, lhs)); | 153 | return Some(postfix_expr(p, lhs)); |
140 | } | 154 | } |
141 | }; | 155 | }; |
142 | unary_expr(p, r); | 156 | expr_bp(p, r, 255); |
143 | Some(m.complete(p, kind)) | 157 | Some(m.complete(p, kind)) |
144 | } | 158 | } |
145 | 159 | ||
@@ -154,6 +168,13 @@ fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { | |||
154 | field_expr(p, lhs) | 168 | field_expr(p, lhs) |
155 | }, | 169 | }, |
156 | DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs), | 170 | DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs), |
171 | // test postfix_range | ||
172 | // fn foo() { let x = 1..; } | ||
173 | DOTDOT if !EXPR_FIRST.contains(p.nth(1)) => { | ||
174 | let m = lhs.precede(p); | ||
175 | p.bump(); | ||
176 | m.complete(p, RANGE_EXPR) | ||
177 | } | ||
157 | QUESTION => try_expr(p, lhs), | 178 | QUESTION => try_expr(p, lhs), |
158 | _ => break, | 179 | _ => break, |
159 | } | 180 | } |
diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index 8855e980e..8db006e54 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs | |||
@@ -148,6 +148,7 @@ pub enum SyntaxKind { | |||
148 | REF_EXPR, | 148 | REF_EXPR, |
149 | DEREF_EXPR, | 149 | DEREF_EXPR, |
150 | NOT_EXPR, | 150 | NOT_EXPR, |
151 | RANGE_EXPR, | ||
151 | BIN_EXPR, | 152 | BIN_EXPR, |
152 | EXTERN_BLOCK_EXPR, | 153 | EXTERN_BLOCK_EXPR, |
153 | ENUM_VARIANT, | 154 | ENUM_VARIANT, |
@@ -375,6 +376,7 @@ impl SyntaxKind { | |||
375 | REF_EXPR => &SyntaxInfo { name: "REF_EXPR" }, | 376 | REF_EXPR => &SyntaxInfo { name: "REF_EXPR" }, |
376 | DEREF_EXPR => &SyntaxInfo { name: "DEREF_EXPR" }, | 377 | DEREF_EXPR => &SyntaxInfo { name: "DEREF_EXPR" }, |
377 | NOT_EXPR => &SyntaxInfo { name: "NOT_EXPR" }, | 378 | NOT_EXPR => &SyntaxInfo { name: "NOT_EXPR" }, |
379 | RANGE_EXPR => &SyntaxInfo { name: "RANGE_EXPR" }, | ||
378 | BIN_EXPR => &SyntaxInfo { name: "BIN_EXPR" }, | 380 | BIN_EXPR => &SyntaxInfo { name: "BIN_EXPR" }, |
379 | EXTERN_BLOCK_EXPR => &SyntaxInfo { name: "EXTERN_BLOCK_EXPR" }, | 381 | EXTERN_BLOCK_EXPR => &SyntaxInfo { name: "EXTERN_BLOCK_EXPR" }, |
380 | ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" }, | 382 | ENUM_VARIANT => &SyntaxInfo { name: "ENUM_VARIANT" }, |
diff --git a/tests/data/parser/inline/0082_range_binding_power.rs b/tests/data/parser/inline/0082_range_binding_power.rs new file mode 100644 index 000000000..259ec31e2 --- /dev/null +++ b/tests/data/parser/inline/0082_range_binding_power.rs | |||
@@ -0,0 +1,5 @@ | |||
1 | fn foo() { | ||
2 | .. 1 + 1; | ||
3 | .. z = 2; | ||
4 | x = false .. 1 == 1; | ||
5 | } | ||
diff --git a/tests/data/parser/inline/0082_range_binding_power.txt b/tests/data/parser/inline/0082_range_binding_power.txt new file mode 100644 index 000000000..0b7bfd56a --- /dev/null +++ b/tests/data/parser/inline/0082_range_binding_power.txt | |||
@@ -0,0 +1,72 @@ | |||
1 | FILE@[0; 66) | ||
2 | FN_ITEM@[0; 66) | ||
3 | FN_KW@[0; 2) | ||
4 | NAME@[2; 6) | ||
5 | WHITESPACE@[2; 3) | ||
6 | IDENT@[3; 6) "foo" | ||
7 | PARAM_LIST@[6; 9) | ||
8 | L_PAREN@[6; 7) | ||
9 | R_PAREN@[7; 8) | ||
10 | WHITESPACE@[8; 9) | ||
11 | BLOCK_EXPR@[9; 66) | ||
12 | L_CURLY@[9; 10) | ||
13 | EXPR_STMT@[10; 29) | ||
14 | RANGE_EXPR@[10; 23) | ||
15 | WHITESPACE@[10; 15) | ||
16 | DOTDOT@[15; 17) | ||
17 | BIN_EXPR@[17; 23) | ||
18 | LITERAL@[17; 20) | ||
19 | WHITESPACE@[17; 18) | ||
20 | INT_NUMBER@[18; 19) "1" | ||
21 | WHITESPACE@[19; 20) | ||
22 | PLUS@[20; 21) | ||
23 | LITERAL@[21; 23) | ||
24 | WHITESPACE@[21; 22) | ||
25 | INT_NUMBER@[22; 23) "1" | ||
26 | SEMI@[23; 24) | ||
27 | WHITESPACE@[24; 29) | ||
28 | EXPR_STMT@[29; 43) | ||
29 | BIN_EXPR@[29; 37) | ||
30 | RANGE_EXPR@[29; 34) | ||
31 | DOTDOT@[29; 31) | ||
32 | PATH_EXPR@[31; 34) | ||
33 | PATH@[31; 34) | ||
34 | PATH_SEGMENT@[31; 34) | ||
35 | NAME_REF@[31; 34) | ||
36 | WHITESPACE@[31; 32) | ||
37 | IDENT@[32; 33) "z" | ||
38 | WHITESPACE@[33; 34) | ||
39 | EQ@[34; 35) | ||
40 | LITERAL@[35; 37) | ||
41 | WHITESPACE@[35; 36) | ||
42 | INT_NUMBER@[36; 37) "2" | ||
43 | SEMI@[37; 38) | ||
44 | WHITESPACE@[38; 43) | ||
45 | EXPR_STMT@[43; 64) | ||
46 | BIN_EXPR@[43; 62) | ||
47 | PATH_EXPR@[43; 45) | ||
48 | PATH@[43; 45) | ||
49 | PATH_SEGMENT@[43; 45) | ||
50 | NAME_REF@[43; 45) | ||
51 | IDENT@[43; 44) "x" | ||
52 | WHITESPACE@[44; 45) | ||
53 | EQ@[45; 46) | ||
54 | BIN_EXPR@[46; 62) | ||
55 | LITERAL@[46; 53) | ||
56 | WHITESPACE@[46; 47) | ||
57 | FALSE_KW@[47; 52) | ||
58 | WHITESPACE@[52; 53) | ||
59 | DOTDOT@[53; 55) | ||
60 | BIN_EXPR@[55; 62) | ||
61 | LITERAL@[55; 58) | ||
62 | WHITESPACE@[55; 56) | ||
63 | INT_NUMBER@[56; 57) "1" | ||
64 | WHITESPACE@[57; 58) | ||
65 | EQEQ@[58; 60) | ||
66 | LITERAL@[60; 62) | ||
67 | WHITESPACE@[60; 61) | ||
68 | INT_NUMBER@[61; 62) "1" | ||
69 | SEMI@[62; 63) | ||
70 | WHITESPACE@[63; 64) | ||
71 | R_CURLY@[64; 65) | ||
72 | WHITESPACE@[65; 66) | ||
diff --git a/tests/data/parser/inline/0083_postfix_range.rs b/tests/data/parser/inline/0083_postfix_range.rs new file mode 100644 index 000000000..c39fe8e68 --- /dev/null +++ b/tests/data/parser/inline/0083_postfix_range.rs | |||
@@ -0,0 +1 @@ | |||
fn foo() { let x = 1..; } | |||
diff --git a/tests/data/parser/inline/0083_postfix_range.txt b/tests/data/parser/inline/0083_postfix_range.txt new file mode 100644 index 000000000..6a77e3a71 --- /dev/null +++ b/tests/data/parser/inline/0083_postfix_range.txt | |||
@@ -0,0 +1,30 @@ | |||
1 | FILE@[0; 26) | ||
2 | FN_ITEM@[0; 26) | ||
3 | FN_KW@[0; 2) | ||
4 | NAME@[2; 6) | ||
5 | WHITESPACE@[2; 3) | ||
6 | IDENT@[3; 6) "foo" | ||
7 | PARAM_LIST@[6; 9) | ||
8 | L_PAREN@[6; 7) | ||
9 | R_PAREN@[7; 8) | ||
10 | WHITESPACE@[8; 9) | ||
11 | BLOCK_EXPR@[9; 26) | ||
12 | L_CURLY@[9; 10) | ||
13 | LET_STMT@[10; 24) | ||
14 | WHITESPACE@[10; 11) | ||
15 | LET_KW@[11; 14) | ||
16 | BIND_PAT@[14; 17) | ||
17 | NAME@[14; 17) | ||
18 | WHITESPACE@[14; 15) | ||
19 | IDENT@[15; 16) "x" | ||
20 | WHITESPACE@[16; 17) | ||
21 | EQ@[17; 18) | ||
22 | RANGE_EXPR@[18; 22) | ||
23 | LITERAL@[18; 20) | ||
24 | WHITESPACE@[18; 19) | ||
25 | INT_NUMBER@[19; 20) "1" | ||
26 | DOTDOT@[20; 22) | ||
27 | SEMI@[22; 23) | ||
28 | WHITESPACE@[23; 24) | ||
29 | R_CURLY@[24; 25) | ||
30 | WHITESPACE@[25; 26) | ||