aboutsummaryrefslogtreecommitdiff
path: root/src/grammar/expressions/mod.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-04 14:58:22 +0100
committerAleksey Kladov <[email protected]>2018-08-04 14:58:22 +0100
commitc5483822520e9c754f3ec8b9eb8e68bd5ef7c373 (patch)
tree5c1b0cd74781a4289c3b6269d5e77e9fc69eadd1 /src/grammar/expressions/mod.rs
parent23cbe7fd4a048ba44aee647b3b7d5a7f3aa575da (diff)
move atoms to a separate file
Diffstat (limited to 'src/grammar/expressions/mod.rs')
-rw-r--r--src/grammar/expressions/mod.rs255
1 files changed, 255 insertions, 0 deletions
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}