aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/grammar.ron1
-rw-r--r--src/grammar/expressions/atom.rs4
-rw-r--r--src/grammar/expressions/mod.rs47
-rw-r--r--src/grammar/patterns.rs23
-rw-r--r--src/syntax_kinds/generated.rs2
5 files changed, 62 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;
6const EXPR_FIRST: TokenSet = LHS_FIRST; 6const EXPR_FIRST: TokenSet = LHS_FIRST;
7 7
8pub(super) fn expr(p: &mut Parser) -> BlockLike { 8pub(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
13pub(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
13fn expr_no_struct(p: &mut Parser) { 18fn 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)]
32struct Restrictions { 37struct Restrictions {
33 forbid_structs: bool 38 forbid_structs: bool,
39 prefer_stmt: bool,
34} 40}
35 41
36enum Op { 42enum 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.
88fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { 94fn 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
181fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { 192fn 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// }
136fn 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" },