aboutsummaryrefslogtreecommitdiff
path: root/src/grammar/expressions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/grammar/expressions.rs')
-rw-r--r--src/grammar/expressions.rs491
1 files changed, 0 insertions, 491 deletions
diff --git a/src/grammar/expressions.rs b/src/grammar/expressions.rs
deleted file mode 100644
index ecca2a3f9..000000000
--- a/src/grammar/expressions.rs
+++ /dev/null
@@ -1,491 +0,0 @@
1use super::*;
2
3// test expr_literals
4// fn foo() {
5// let _ = true;
6// let _ = false;
7// let _ = 1;
8// let _ = 2.0;
9// let _ = b'a';
10// let _ = 'b';
11// let _ = "c";
12// let _ = r"d";
13// let _ = b"e";
14// let _ = br"f";
15// }
16const LITERAL_FIRST: TokenSet =
17 token_set![TRUE_KW, FALSE_KW, INT_NUMBER, FLOAT_NUMBER, BYTE, CHAR,
18 STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING];
19
20pub(super) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
21 if !LITERAL_FIRST.contains(p.current()) {
22 return None;
23 }
24 let m = p.start();
25 p.bump();
26 Some(m.complete(p, LITERAL))
27}
28
29const EXPR_FIRST: TokenSet = PREFIX_EXPR_FIRST;
30
31pub(super) fn expr(p: &mut Parser) {
32 expr_bp(p, 1)
33}
34
35fn bp_of(op: SyntaxKind) -> u8 {
36 match op {
37 EQEQ | NEQ => 1,
38 MINUS | PLUS => 2,
39 STAR | SLASH => 3,
40 _ => 0
41 }
42}
43
44
45// test expr_binding_power
46// fn foo() {
47// 1 + 2 * 3 == 1 * 2 + 3
48// }
49
50// Parses expression with binding power of at least bp.
51fn expr_bp(p: &mut Parser, bp: u8) {
52 let mut lhs = match unary_expr(p) {
53 Some(lhs) => lhs,
54 None => return,
55 };
56
57 loop {
58 let op_bp = bp_of(p.current());
59 if op_bp < bp {
60 break;
61 }
62 lhs = bin_expr(p, lhs, op_bp);
63 }
64}
65
66fn unary_expr(p: &mut Parser) -> Option<CompletedMarker> {
67 let done = match p.current() {
68 AMPERSAND => ref_expr(p),
69 STAR => deref_expr(p),
70 EXCL => not_expr(p),
71 _ => {
72 let lhs = atom_expr(p)?;
73 postfix_expr(p, lhs)
74 }
75 };
76 Some(done)
77}
78
79fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker {
80 loop {
81 lhs = match p.current() {
82 L_PAREN => call_expr(p, lhs),
83 DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN {
84 method_call_expr(p, lhs)
85 } else {
86 field_expr(p, lhs)
87 },
88 DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs),
89 QUESTION => try_expr(p, lhs),
90 _ => break,
91 }
92 }
93 lhs
94}
95
96// test block
97// fn a() {}
98// fn b() { let _ = 1; }
99// fn c() { 1; 2; }
100// fn d() { 1; 2 }
101pub(super) fn block(p: &mut Parser) {
102 if !p.at(L_CURLY) {
103 p.error("expected block");
104 return;
105 }
106 block_expr(p);
107}
108
109// test let_stmt;
110// fn foo() {
111// let a;
112// let b: i32;
113// let c = 92;
114// let d: i32 = 92;
115// }
116fn let_stmt(p: &mut Parser) {
117 assert!(p.at(LET_KW));
118 let m = p.start();
119 p.bump();
120 patterns::pattern(p);
121 if p.at(COLON) {
122 types::ascription(p);
123 }
124 if p.eat(EQ) {
125 expressions::expr(p);
126 }
127 p.expect(SEMI);
128 m.complete(p, LET_STMT);
129}
130
131const PREFIX_EXPR_FIRST: TokenSet =
132 token_set_union![
133 token_set![AMPERSAND, STAR, EXCL],
134 ATOM_EXPR_FIRST,
135 ];
136
137// test ref_expr
138// fn foo() {
139// let _ = &1;
140// let _ = &mut &f();
141// }
142fn ref_expr(p: &mut Parser) -> CompletedMarker {
143 assert!(p.at(AMPERSAND));
144 let m = p.start();
145 p.bump();
146 p.eat(MUT_KW);
147 expr(p);
148 m.complete(p, REF_EXPR)
149}
150
151// test deref_expr
152// fn foo() {
153// **&1;
154// }
155fn deref_expr(p: &mut Parser) -> CompletedMarker {
156 assert!(p.at(STAR));
157 let m = p.start();
158 p.bump();
159 expr(p);
160 m.complete(p, DEREF_EXPR)
161}
162
163// test not_expr
164// fn foo() {
165// !!true;
166// }
167fn not_expr(p: &mut Parser) -> CompletedMarker {
168 assert!(p.at(EXCL));
169 let m = p.start();
170 p.bump();
171 expr(p);
172 m.complete(p, NOT_EXPR)
173}
174
175const ATOM_EXPR_FIRST: TokenSet =
176 token_set_union![
177 LITERAL_FIRST,
178 token_set![L_PAREN, PIPE, MOVE_KW, IF_KW, UNSAFE_KW, L_CURLY, RETURN_KW],
179 ];
180
181fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> {
182 match literal(p) {
183 Some(m) => return Some(m),
184 None => (),
185 }
186 if paths::is_path_start(p) {
187 return Some(path_expr(p));
188 }
189 let la = p.nth(1);
190 let done = match p.current() {
191 L_PAREN => tuple_expr(p),
192 PIPE => lambda_expr(p),
193 MOVE_KW if la == PIPE => lambda_expr(p),
194 IF_KW => if_expr(p),
195 MATCH_KW => match_expr(p),
196 UNSAFE_KW if la == L_CURLY => block_expr(p),
197 L_CURLY => block_expr(p),
198 RETURN_KW => return_expr(p),
199 _ => {
200 p.err_and_bump("expected expression");
201 return None;
202 }
203 };
204 Some(done)
205}
206
207fn tuple_expr(p: &mut Parser) -> CompletedMarker {
208 assert!(p.at(L_PAREN));
209 let m = p.start();
210 p.expect(L_PAREN);
211 p.expect(R_PAREN);
212 m.complete(p, TUPLE_EXPR)
213}
214
215// test lambda_expr
216// fn foo() {
217// || ();
218// || -> i32 { 92 };
219// |x| x;
220// move |x: i32,| x;
221// }
222fn lambda_expr(p: &mut Parser) -> CompletedMarker {
223 assert!(p.at(PIPE) || (p.at(MOVE_KW) && p.nth(1) == PIPE));
224 let m = p.start();
225 p.eat(MOVE_KW);
226 params::param_list_opt_types(p);
227 if fn_ret_type(p) {
228 block(p);
229 } else {
230 expr(p)
231 }
232 m.complete(p, LAMBDA_EXPR)
233}
234
235// test if_expr
236// fn foo() {
237// if true {};
238// if true {} else {};
239// if true {} else if false {} else {}
240// }
241fn if_expr(p: &mut Parser) -> CompletedMarker {
242 assert!(p.at(IF_KW));
243 let m = p.start();
244 if_head(p);
245 block(p);
246 if p.at(ELSE_KW) {
247 p.bump();
248 if p.at(IF_KW) {
249 if_expr(p);
250 } else {
251 block(p);
252 }
253 }
254 m.complete(p, IF_EXPR)
255}
256
257fn if_head(p: &mut Parser) {
258 assert!(p.at(IF_KW));
259 p.bump();
260 expr(p);
261}
262
263// test match_expr
264// fn foo() {
265// match () { };
266// }
267fn match_expr(p: &mut Parser) -> CompletedMarker {
268 assert!(p.at(MATCH_KW));
269 let m = p.start();
270 p.bump();
271 expr(p);
272 p.eat(L_CURLY);
273 while !p.at(EOF) && !p.at(R_CURLY) {
274 match_arm(p);
275 if !p.at(R_CURLY) {
276 p.expect(COMMA);
277 }
278 }
279 p.expect(R_CURLY);
280 m.complete(p, MATCH_EXPR)
281}
282
283// test match_arm
284// fn foo() {
285// match () {
286// _ => (),
287// X | Y if Z => (),
288// };
289// }
290fn match_arm(p: &mut Parser) {
291 let m = p.start();
292 loop {
293 patterns::pattern(p);
294 if !p.eat(PIPE) {
295 break;
296 }
297 }
298 if p.at(IF_KW) {
299 if_head(p)
300 }
301 p.expect(FAT_ARROW);
302 expr(p);
303 m.complete(p, MATCH_ARM);
304}
305
306// test block_expr
307// fn foo() {
308// {};
309// unsafe {};
310// }
311fn block_expr(p: &mut Parser) -> CompletedMarker {
312 assert!(p.at(L_CURLY) || p.at(UNSAFE_KW) && p.nth(1) == L_CURLY);
313 let m = p.start();
314 p.eat(UNSAFE_KW);
315 p.bump();
316 while !p.at(EOF) && !p.at(R_CURLY) {
317 match p.current() {
318 LET_KW => let_stmt(p),
319 _ => {
320 // test block_items
321 // fn a() { fn b() {} }
322 let m = p.start();
323 match items::maybe_item(p) {
324 items::MaybeItem::Item(kind) => {
325 m.complete(p, kind);
326 }
327 items::MaybeItem::Modifiers => {
328 m.abandon(p);
329 p.error("expected an item");
330 }
331 // test pub_expr
332 // fn foo() { pub 92; } //FIXME
333 items::MaybeItem::None => {
334 expressions::expr(p);
335 if p.eat(SEMI) {
336 m.complete(p, EXPR_STMT);
337 } else {
338 m.abandon(p);
339 }
340 }
341 }
342 }
343 }
344 }
345 p.expect(R_CURLY);
346 m.complete(p, BLOCK_EXPR)
347}
348
349// test return_expr
350// fn foo() {
351// return;
352// return 92;
353// }
354fn return_expr(p: &mut Parser) -> CompletedMarker {
355 assert!(p.at(RETURN_KW));
356 let m = p.start();
357 p.bump();
358 if EXPR_FIRST.contains(p.current()) {
359 expr(p);
360 }
361 m.complete(p, RETURN_EXPR)
362}
363
364// test call_expr
365// fn foo() {
366// let _ = f();
367// let _ = f()(1)(1, 2,);
368// }
369fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
370 assert!(p.at(L_PAREN));
371 let m = lhs.precede(p);
372 arg_list(p);
373 m.complete(p, CALL_EXPR)
374}
375
376// test method_call_expr
377// fn foo() {
378// x.foo();
379// y.bar(1, 2,);
380// }
381fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
382 assert!(p.at(DOT) && p.nth(1) == IDENT && p.nth(2) == L_PAREN);
383 let m = lhs.precede(p);
384 p.bump();
385 name_ref(p);
386 arg_list(p);
387 m.complete(p, METHOD_CALL_EXPR)
388}
389
390// test field_expr
391// fn foo() {
392// x.foo;
393// x.0.bar;
394// }
395fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
396 assert!(p.at(DOT) && (p.nth(1) == IDENT || p.nth(1) == INT_NUMBER));
397 let m = lhs.precede(p);
398 p.bump();
399 if p.at(IDENT) {
400 name_ref(p)
401 } else {
402 p.bump()
403 }
404 m.complete(p, FIELD_EXPR)
405}
406
407// test try_expr
408// fn foo() {
409// x?;
410// }
411fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
412 assert!(p.at(QUESTION));
413 let m = lhs.precede(p);
414 p.bump();
415 m.complete(p, TRY_EXPR)
416}
417
418fn arg_list(p: &mut Parser) {
419 assert!(p.at(L_PAREN));
420 let m = p.start();
421 p.bump();
422 while !p.at(R_PAREN) && !p.at(EOF) {
423 expr(p);
424 if !p.at(R_PAREN) && !p.expect(COMMA) {
425 break;
426 }
427 }
428 p.eat(R_PAREN);
429 m.complete(p, ARG_LIST);
430}
431
432// test path_expr
433// fn foo() {
434// let _ = a;
435// let _ = a::b;
436// let _ = ::a::<b>;
437// }
438fn path_expr(p: &mut Parser) -> CompletedMarker {
439 assert!(paths::is_path_start(p));
440 let m = p.start();
441 paths::expr_path(p);
442 if p.at(L_CURLY) {
443 struct_lit(p);
444 m.complete(p, STRUCT_LIT)
445 } else {
446 m.complete(p, PATH_EXPR)
447 }
448}
449
450// test struct_lit
451// fn foo() {
452// S {};
453// S { x, y: 32, };
454// S { x, y: 32, ..Default::default() };
455// }
456fn struct_lit(p: &mut Parser) {
457 assert!(p.at(L_CURLY));
458 p.bump();
459 while !p.at(EOF) && !p.at(R_CURLY) {
460 match p.current() {
461 IDENT => {
462 let m = p.start();
463 name_ref(p);
464 if p.eat(COLON) {
465 expr(p);
466 }
467 m.complete(p, STRUCT_LIT_FIELD);
468 }
469 DOTDOT => {
470 p.bump();
471 expr(p);
472 }
473 _ => p.err_and_bump("expected identifier"),
474 }
475 if !p.at(R_CURLY) {
476 p.expect(COMMA);
477 }
478 }
479 p.expect(R_CURLY);
480}
481
482fn bin_expr(p: &mut Parser, lhs: CompletedMarker, bp: u8) -> CompletedMarker {
483 assert!(match p.current() {
484 MINUS | PLUS | STAR | SLASH | EQEQ | NEQ => true,
485 _ => false,
486 });
487 let m = lhs.precede(p);
488 p.bump();
489 expr_bp(p, bp);
490 m.complete(p, BIN_EXPR)
491}