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.rs284
1 files changed, 284 insertions, 0 deletions
diff --git a/src/grammar/expressions.rs b/src/grammar/expressions.rs
new file mode 100644
index 000000000..06f9105c6
--- /dev/null
+++ b/src/grammar/expressions.rs
@@ -0,0 +1,284 @@
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// }
16pub(super) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
17 match p.current() {
18 TRUE_KW | FALSE_KW | INT_NUMBER | FLOAT_NUMBER | BYTE | CHAR | STRING | RAW_STRING
19 | BYTE_STRING | RAW_BYTE_STRING => {
20 let m = p.start();
21 p.bump();
22 Some(m.complete(p, LITERAL))
23 }
24 _ => None,
25 }
26}
27
28pub(super) fn expr(p: &mut Parser) {
29 let mut lhs = match prefix_expr(p) {
30 Some(lhs) => lhs,
31 None => return,
32 };
33
34 loop {
35 lhs = match p.current() {
36 L_PAREN => call_expr(p, lhs),
37 DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN {
38 method_call_expr(p, lhs)
39 } else {
40 field_expr(p, lhs)
41 },
42 _ => break,
43 }
44 }
45}
46
47// test block
48// fn a() {}
49// fn b() { let _ = 1; }
50// fn c() { 1; 2; }
51// fn d() { 1; 2 }
52pub(super) fn block(p: &mut Parser) {
53 if !p.at(L_CURLY) {
54 p.error("expected block");
55 }
56 let m = p.start();
57 p.bump();
58 while !p.at(EOF) && !p.at(R_CURLY) {
59 match p.current() {
60 LET_KW => let_stmt(p),
61 c => {
62 // test block_items
63 // fn a() { fn b() {} }
64 if items::ITEM_FIRST.contains(c) {
65 items::item(p)
66 } else {
67 let expr_stmt = p.start();
68 expressions::expr(p);
69 if p.eat(SEMI) {
70 expr_stmt.complete(p, EXPR_STMT);
71 } else {
72 expr_stmt.abandon(p);
73 }
74 }
75 }
76 }
77 }
78 p.expect(R_CURLY);
79 m.complete(p, BLOCK);
80}
81
82// test let_stmt;
83// fn foo() {
84// let a;
85// let b: i32;
86// let c = 92;
87// let d: i32 = 92;
88// }
89fn let_stmt(p: &mut Parser) {
90 assert!(p.at(LET_KW));
91 let m = p.start();
92 p.bump();
93 patterns::pattern(p);
94 if p.at(COLON) {
95 types::ascription(p);
96 }
97 if p.eat(EQ) {
98 expressions::expr(p);
99 }
100 p.expect(SEMI);
101 m.complete(p, LET_STMT);
102}
103
104fn prefix_expr(p: &mut Parser) -> Option<CompletedMarker> {
105 match p.current() {
106 AMPERSAND => Some(ref_expr(p)),
107 STAR => Some(deref_expr(p)),
108 _ => atom_expr(p),
109 }
110}
111
112// test ref_expr
113// fn foo() {
114// let _ = &1;
115// let _ = &mut &f();
116// }
117fn ref_expr(p: &mut Parser) -> CompletedMarker {
118 assert!(p.at(AMPERSAND));
119 let m = p.start();
120 p.bump();
121 p.eat(MUT_KW);
122 expr(p);
123 m.complete(p, REF_EXPR)
124}
125
126// test deref_expr
127// fn foo() {
128// **&1;
129// }
130fn deref_expr(p: &mut Parser) -> CompletedMarker {
131 assert!(p.at(STAR));
132 let m = p.start();
133 p.bump();
134 expr(p);
135 m.complete(p, DEREF_EXPR)
136}
137
138fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> {
139 match literal(p) {
140 Some(m) => return Some(m),
141 None => (),
142 }
143 if paths::is_path_start(p) {
144 return Some(path_expr(p));
145 }
146
147 match p.current() {
148 L_PAREN => Some(tuple_expr(p)),
149 PIPE => Some(lambda_expr(p)),
150 _ => {
151 p.err_and_bump("expected expression");
152 None
153 }
154 }
155}
156
157fn tuple_expr(p: &mut Parser) -> CompletedMarker {
158 assert!(p.at(L_PAREN));
159 let m = p.start();
160 p.expect(L_PAREN);
161 p.expect(R_PAREN);
162 m.complete(p, TUPLE_EXPR)
163}
164
165// test lambda_expr
166// fn foo() {
167// || ();
168// || -> i32 { 92 };
169// |x| x;
170// |x: i32,| x;
171// }
172fn lambda_expr(p: &mut Parser) -> CompletedMarker {
173 assert!(p.at(PIPE));
174 let m = p.start();
175 params::param_list_opt_types(p);
176 if fn_ret_type(p) {
177 block(p);
178 } else {
179 expr(p)
180 }
181 m.complete(p, LAMBDA_EXPR)
182}
183
184// test call_expr
185// fn foo() {
186// let _ = f();
187// let _ = f()(1)(1, 2,);
188// }
189fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
190 assert!(p.at(L_PAREN));
191 let m = lhs.precede(p);
192 arg_list(p);
193 m.complete(p, CALL_EXPR)
194}
195
196// test method_call_expr
197// fn foo() {
198// x.foo();
199// y.bar(1, 2,);
200// }
201fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
202 assert!(p.at(DOT) && p.nth(1) == IDENT && p.nth(2) == L_PAREN);
203 let m = lhs.precede(p);
204 p.bump();
205 p.bump();
206 arg_list(p);
207 m.complete(p, METHOD_CALL_EXPR)
208}
209
210// test field_expr
211// fn foo() {
212// x.foo.bar;
213// }
214fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
215 assert!(p.at(DOT) && p.nth(1) == IDENT);
216 let m = lhs.precede(p);
217 p.bump();
218 p.bump();
219 m.complete(p, FIELD_EXPR)
220}
221
222fn arg_list(p: &mut Parser) {
223 assert!(p.at(L_PAREN));
224 let m = p.start();
225 p.bump();
226 while !p.at(R_PAREN) && !p.at(EOF) {
227 expr(p);
228 if !p.at(R_PAREN) && !p.expect(COMMA) {
229 break;
230 }
231 }
232 p.eat(R_PAREN);
233 m.complete(p, ARG_LIST);
234}
235
236// test path_expr
237// fn foo() {
238// let _ = a;
239// let _ = a::b;
240// let _ = ::a::<b>;
241// }
242fn path_expr(p: &mut Parser) -> CompletedMarker {
243 assert!(paths::is_path_start(p));
244 let m = p.start();
245 paths::expr_path(p);
246 if p.at(L_CURLY) {
247 struct_lit(p);
248 m.complete(p, STRUCT_LIT)
249 } else {
250 m.complete(p, PATH_EXPR)
251 }
252}
253
254// test struct_lit
255// fn foo() {
256// S {};
257// S { x, y: 32, };
258// S { x, y: 32, ..Default::default() };
259// }
260fn struct_lit(p: &mut Parser) {
261 assert!(p.at(L_CURLY));
262 p.bump();
263 while !p.at(EOF) && !p.at(R_CURLY) {
264 match p.current() {
265 IDENT => {
266 let m = p.start();
267 name_ref(p);
268 if p.eat(COLON) {
269 expr(p);
270 }
271 m.complete(p, STRUCT_LIT_FIELD);
272 }
273 DOTDOT => {
274 p.bump();
275 expr(p);
276 }
277 _ => p.err_and_bump("expected identifier"),
278 }
279 if !p.at(R_CURLY) {
280 p.expect(COMMA);
281 }
282 }
283 p.expect(R_CURLY);
284}