aboutsummaryrefslogtreecommitdiff
path: root/src/grammar
diff options
context:
space:
mode:
Diffstat (limited to 'src/grammar')
-rw-r--r--src/grammar/expressions.rs491
-rw-r--r--src/grammar/expressions/atom.rs239
-rw-r--r--src/grammar/expressions/mod.rs255
3 files changed, 494 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}
diff --git a/src/grammar/expressions/atom.rs b/src/grammar/expressions/atom.rs
new file mode 100644
index 000000000..95c811730
--- /dev/null
+++ b/src/grammar/expressions/atom.rs
@@ -0,0 +1,239 @@
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(crate) 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
29pub(super) const ATOM_EXPR_FIRST: TokenSet =
30 token_set_union![
31 LITERAL_FIRST,
32 token_set![L_PAREN, PIPE, MOVE_KW, IF_KW, MATCH_KW, UNSAFE_KW, L_CURLY, RETURN_KW,
33 IDENT, SELF_KW, SUPER_KW, COLONCOLON ],
34 ];
35
36pub(super) fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> {
37 match literal(p) {
38 Some(m) => return Some(m),
39 None => (),
40 }
41 if paths::is_path_start(p) {
42 return Some(path_expr(p));
43 }
44 let la = p.nth(1);
45 let done = match p.current() {
46 L_PAREN => tuple_expr(p),
47 PIPE => lambda_expr(p),
48 MOVE_KW if la == PIPE => lambda_expr(p),
49 IF_KW => if_expr(p),
50 MATCH_KW => match_expr(p),
51 UNSAFE_KW if la == L_CURLY => block_expr(p),
52 L_CURLY => block_expr(p),
53 RETURN_KW => return_expr(p),
54 _ => {
55 p.err_and_bump("expected expression");
56 return None;
57 }
58 };
59 Some(done)
60}
61
62fn tuple_expr(p: &mut Parser) -> CompletedMarker {
63 assert!(p.at(L_PAREN));
64 let m = p.start();
65 p.expect(L_PAREN);
66 p.expect(R_PAREN);
67 m.complete(p, TUPLE_EXPR)
68}
69
70// test lambda_expr
71// fn foo() {
72// || ();
73// || -> i32 { 92 };
74// |x| x;
75// move |x: i32,| x;
76// }
77fn lambda_expr(p: &mut Parser) -> CompletedMarker {
78 assert!(p.at(PIPE) || (p.at(MOVE_KW) && p.nth(1) == PIPE));
79 let m = p.start();
80 p.eat(MOVE_KW);
81 params::param_list_opt_types(p);
82 if fn_ret_type(p) {
83 block(p);
84 } else {
85 expr(p)
86 }
87 m.complete(p, LAMBDA_EXPR)
88}
89
90// test if_expr
91// fn foo() {
92// if true {};
93// if true {} else {};
94// if true {} else if false {} else {}
95// }
96fn if_expr(p: &mut Parser) -> CompletedMarker {
97 assert!(p.at(IF_KW));
98 let m = p.start();
99 if_head(p);
100 block(p);
101 if p.at(ELSE_KW) {
102 p.bump();
103 if p.at(IF_KW) {
104 if_expr(p);
105 } else {
106 block(p);
107 }
108 }
109 m.complete(p, IF_EXPR)
110}
111
112fn if_head(p: &mut Parser) {
113 assert!(p.at(IF_KW));
114 p.bump();
115 expr(p);
116}
117
118// test match_expr
119// fn foo() {
120// match () { };
121// }
122fn match_expr(p: &mut Parser) -> CompletedMarker {
123 assert!(p.at(MATCH_KW));
124 let m = p.start();
125 p.bump();
126 expr(p);
127 p.eat(L_CURLY);
128 while !p.at(EOF) && !p.at(R_CURLY) {
129 match_arm(p);
130 if !p.at(R_CURLY) {
131 p.expect(COMMA);
132 }
133 }
134 p.expect(R_CURLY);
135 m.complete(p, MATCH_EXPR)
136}
137
138// test match_arm
139// fn foo() {
140// match () {
141// _ => (),
142// X | Y if Z => (),
143// };
144// }
145fn match_arm(p: &mut Parser) {
146 let m = p.start();
147 loop {
148 patterns::pattern(p);
149 if !p.eat(PIPE) {
150 break;
151 }
152 }
153 if p.at(IF_KW) {
154 if_head(p)
155 }
156 p.expect(FAT_ARROW);
157 expr(p);
158 m.complete(p, MATCH_ARM);
159}
160
161// test block_expr
162// fn foo() {
163// {};
164// unsafe {};
165// }
166pub(super) fn block_expr(p: &mut Parser) -> CompletedMarker {
167 assert!(p.at(L_CURLY) || p.at(UNSAFE_KW) && p.nth(1) == L_CURLY);
168 let m = p.start();
169 p.eat(UNSAFE_KW);
170 p.bump();
171 while !p.at(EOF) && !p.at(R_CURLY) {
172 match p.current() {
173 LET_KW => let_stmt(p),
174 _ => {
175 // test block_items
176 // fn a() { fn b() {} }
177 let m = p.start();
178 match items::maybe_item(p) {
179 items::MaybeItem::Item(kind) => {
180 m.complete(p, kind);
181 }
182 items::MaybeItem::Modifiers => {
183 m.abandon(p);
184 p.error("expected an item");
185 }
186 // test pub_expr
187 // fn foo() { pub 92; } //FIXME
188 items::MaybeItem::None => {
189 expressions::expr(p);
190 if p.eat(SEMI) {
191 m.complete(p, EXPR_STMT);
192 } else {
193 m.abandon(p);
194 }
195 }
196 }
197 }
198 }
199 }
200 p.expect(R_CURLY);
201 m.complete(p, BLOCK_EXPR)
202}
203
204// test let_stmt;
205// fn foo() {
206// let a;
207// let b: i32;
208// let c = 92;
209// let d: i32 = 92;
210// }
211fn let_stmt(p: &mut Parser) {
212 assert!(p.at(LET_KW));
213 let m = p.start();
214 p.bump();
215 patterns::pattern(p);
216 if p.at(COLON) {
217 types::ascription(p);
218 }
219 if p.eat(EQ) {
220 expressions::expr(p);
221 }
222 p.expect(SEMI);
223 m.complete(p, LET_STMT);
224}
225
226// test return_expr
227// fn foo() {
228// return;
229// return 92;
230// }
231fn return_expr(p: &mut Parser) -> CompletedMarker {
232 assert!(p.at(RETURN_KW));
233 let m = p.start();
234 p.bump();
235 if EXPR_FIRST.contains(p.current()) {
236 expr(p);
237 }
238 m.complete(p, RETURN_EXPR)
239}
diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs
new file mode 100644
index 000000000..f2b0c36f5
--- /dev/null
+++ b/src/grammar/expressions/mod.rs
@@ -0,0 +1,255 @@
1mod atom;
2
3use super::*;
4pub(super) use self::atom::literal;
5
6const EXPR_FIRST: TokenSet = UNARY_EXPR_FIRST;
7
8pub(super) fn expr(p: &mut Parser) {
9 expr_bp(p, 1)
10}
11
12// test block
13// fn a() {}
14// fn b() { let _ = 1; }
15// fn c() { 1; 2; }
16// fn d() { 1; 2 }
17pub(super) fn block(p: &mut Parser) {
18 if !p.at(L_CURLY) {
19 p.error("expected block");
20 return;
21 }
22 atom::block_expr(p);
23}
24
25// test expr_binding_power
26// fn foo() {
27// 1 + 2 * 3 == 1 * 2 + 3
28// }
29fn bp_of(op: SyntaxKind) -> u8 {
30 match op {
31 EQEQ | NEQ => 1,
32 MINUS | PLUS => 2,
33 STAR | SLASH => 3,
34 _ => 0
35 }
36}
37
38// Parses expression with binding power of at least bp.
39fn expr_bp(p: &mut Parser, bp: u8) {
40 let mut lhs = match unary_expr(p) {
41 Some(lhs) => lhs,
42 None => return,
43 };
44
45 loop {
46 let op_bp = bp_of(p.current());
47 if op_bp < bp {
48 break;
49 }
50 lhs = bin_expr(p, lhs, op_bp);
51 }
52}
53
54const UNARY_EXPR_FIRST: TokenSet =
55 token_set_union![
56 token_set![AMPERSAND, STAR, EXCL],
57 atom::ATOM_EXPR_FIRST,
58 ];
59
60fn unary_expr(p: &mut Parser) -> Option<CompletedMarker> {
61 let done = match p.current() {
62 AMPERSAND => ref_expr(p),
63 STAR => deref_expr(p),
64 EXCL => not_expr(p),
65 _ => {
66 let lhs = atom::atom_expr(p)?;
67 postfix_expr(p, lhs)
68 }
69 };
70 Some(done)
71}
72
73fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker {
74 loop {
75 lhs = match p.current() {
76 L_PAREN => call_expr(p, lhs),
77 DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN {
78 method_call_expr(p, lhs)
79 } else {
80 field_expr(p, lhs)
81 },
82 DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs),
83 QUESTION => try_expr(p, lhs),
84 _ => break,
85 }
86 }
87 lhs
88}
89
90// test ref_expr
91// fn foo() {
92// let _ = &1;
93// let _ = &mut &f();
94// }
95fn ref_expr(p: &mut Parser) -> CompletedMarker {
96 assert!(p.at(AMPERSAND));
97 let m = p.start();
98 p.bump();
99 p.eat(MUT_KW);
100 expr(p);
101 m.complete(p, REF_EXPR)
102}
103
104// test deref_expr
105// fn foo() {
106// **&1;
107// }
108fn deref_expr(p: &mut Parser) -> CompletedMarker {
109 assert!(p.at(STAR));
110 let m = p.start();
111 p.bump();
112 expr(p);
113 m.complete(p, DEREF_EXPR)
114}
115
116// test not_expr
117// fn foo() {
118// !!true;
119// }
120fn not_expr(p: &mut Parser) -> CompletedMarker {
121 assert!(p.at(EXCL));
122 let m = p.start();
123 p.bump();
124 expr(p);
125 m.complete(p, NOT_EXPR)
126}
127
128// test call_expr
129// fn foo() {
130// let _ = f();
131// let _ = f()(1)(1, 2,);
132// }
133fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
134 assert!(p.at(L_PAREN));
135 let m = lhs.precede(p);
136 arg_list(p);
137 m.complete(p, CALL_EXPR)
138}
139
140// test method_call_expr
141// fn foo() {
142// x.foo();
143// y.bar(1, 2,);
144// }
145fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
146 assert!(p.at(DOT) && p.nth(1) == IDENT && p.nth(2) == L_PAREN);
147 let m = lhs.precede(p);
148 p.bump();
149 name_ref(p);
150 arg_list(p);
151 m.complete(p, METHOD_CALL_EXPR)
152}
153
154// test field_expr
155// fn foo() {
156// x.foo;
157// x.0.bar;
158// }
159fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
160 assert!(p.at(DOT) && (p.nth(1) == IDENT || p.nth(1) == INT_NUMBER));
161 let m = lhs.precede(p);
162 p.bump();
163 if p.at(IDENT) {
164 name_ref(p)
165 } else {
166 p.bump()
167 }
168 m.complete(p, FIELD_EXPR)
169}
170
171// test try_expr
172// fn foo() {
173// x?;
174// }
175fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
176 assert!(p.at(QUESTION));
177 let m = lhs.precede(p);
178 p.bump();
179 m.complete(p, TRY_EXPR)
180}
181
182fn arg_list(p: &mut Parser) {
183 assert!(p.at(L_PAREN));
184 let m = p.start();
185 p.bump();
186 while !p.at(R_PAREN) && !p.at(EOF) {
187 expr(p);
188 if !p.at(R_PAREN) && !p.expect(COMMA) {
189 break;
190 }
191 }
192 p.eat(R_PAREN);
193 m.complete(p, ARG_LIST);
194}
195
196// test path_expr
197// fn foo() {
198// let _ = a;
199// let _ = a::b;
200// let _ = ::a::<b>;
201// }
202fn path_expr(p: &mut Parser) -> CompletedMarker {
203 assert!(paths::is_path_start(p));
204 let m = p.start();
205 paths::expr_path(p);
206 if p.at(L_CURLY) {
207 struct_lit(p);
208 m.complete(p, STRUCT_LIT)
209 } else {
210 m.complete(p, PATH_EXPR)
211 }
212}
213
214// test struct_lit
215// fn foo() {
216// S {};
217// S { x, y: 32, };
218// S { x, y: 32, ..Default::default() };
219// }
220fn struct_lit(p: &mut Parser) {
221 assert!(p.at(L_CURLY));
222 p.bump();
223 while !p.at(EOF) && !p.at(R_CURLY) {
224 match p.current() {
225 IDENT => {
226 let m = p.start();
227 name_ref(p);
228 if p.eat(COLON) {
229 expr(p);
230 }
231 m.complete(p, STRUCT_LIT_FIELD);
232 }
233 DOTDOT => {
234 p.bump();
235 expr(p);
236 }
237 _ => p.err_and_bump("expected identifier"),
238 }
239 if !p.at(R_CURLY) {
240 p.expect(COMMA);
241 }
242 }
243 p.expect(R_CURLY);
244}
245
246fn bin_expr(p: &mut Parser, lhs: CompletedMarker, bp: u8) -> CompletedMarker {
247 assert!(match p.current() {
248 MINUS | PLUS | STAR | SLASH | EQEQ | NEQ => true,
249 _ => false,
250 });
251 let m = lhs.precede(p);
252 p.bump();
253 expr_bp(p, bp);
254 m.complete(p, BIN_EXPR)
255}