aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-05 16:07:06 +0100
committerAleksey Kladov <[email protected]>2018-08-05 16:07:06 +0100
commitb0291cd8c2ec1d6d164caaa743f7484416e9b3f5 (patch)
tree57a2b21085bf0996d37c3f8d757f0332c5055a5a /src
parent80fa861cd688c8e7c92e27feaf6623ecfaa4901e (diff)
Range expr
Diffstat (limited to 'src')
-rw-r--r--src/grammar.ron1
-rw-r--r--src/grammar/expressions/mod.rs37
-rw-r--r--src/syntax_kinds/generated.rs2
3 files changed, 32 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// }
53fn current_op(p: &Parser) -> (u8, Op) { 60fn 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.
78fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { 86fn 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
105fn unary_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { 113fn 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" },