diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/grammar/expressions/atom.rs | 12 | ||||
-rw-r--r-- | src/grammar/expressions/mod.rs | 110 |
2 files changed, 63 insertions, 59 deletions
diff --git a/src/grammar/expressions/atom.rs b/src/grammar/expressions/atom.rs index 95c811730..ad654df9e 100644 --- a/src/grammar/expressions/atom.rs +++ b/src/grammar/expressions/atom.rs | |||
@@ -33,13 +33,13 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = | |||
33 | IDENT, SELF_KW, SUPER_KW, COLONCOLON ], | 33 | IDENT, SELF_KW, SUPER_KW, COLONCOLON ], |
34 | ]; | 34 | ]; |
35 | 35 | ||
36 | pub(super) fn atom_expr(p: &mut Parser) -> Option<CompletedMarker> { | 36 | pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { |
37 | match literal(p) { | 37 | match literal(p) { |
38 | Some(m) => return Some(m), | 38 | Some(m) => return Some(m), |
39 | None => (), | 39 | None => (), |
40 | } | 40 | } |
41 | if paths::is_path_start(p) { | 41 | if paths::is_path_start(p) { |
42 | return Some(path_expr(p)); | 42 | return Some(path_expr(p, r)); |
43 | } | 43 | } |
44 | let la = p.nth(1); | 44 | let la = p.nth(1); |
45 | let done = match p.current() { | 45 | let done = match p.current() { |
@@ -91,7 +91,8 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { | |||
91 | // fn foo() { | 91 | // fn foo() { |
92 | // if true {}; | 92 | // if true {}; |
93 | // if true {} else {}; | 93 | // if true {} else {}; |
94 | // if true {} else if false {} else {} | 94 | // if true {} else if false {} else {}; |
95 | // if S {}; | ||
95 | // } | 96 | // } |
96 | fn if_expr(p: &mut Parser) -> CompletedMarker { | 97 | fn if_expr(p: &mut Parser) -> CompletedMarker { |
97 | assert!(p.at(IF_KW)); | 98 | assert!(p.at(IF_KW)); |
@@ -112,18 +113,19 @@ fn if_expr(p: &mut Parser) -> CompletedMarker { | |||
112 | fn if_head(p: &mut Parser) { | 113 | fn if_head(p: &mut Parser) { |
113 | assert!(p.at(IF_KW)); | 114 | assert!(p.at(IF_KW)); |
114 | p.bump(); | 115 | p.bump(); |
115 | expr(p); | 116 | expr_no_struct(p); |
116 | } | 117 | } |
117 | 118 | ||
118 | // test match_expr | 119 | // test match_expr |
119 | // fn foo() { | 120 | // fn foo() { |
120 | // match () { }; | 121 | // match () { }; |
122 | // match S {}; | ||
121 | // } | 123 | // } |
122 | fn match_expr(p: &mut Parser) -> CompletedMarker { | 124 | fn match_expr(p: &mut Parser) -> CompletedMarker { |
123 | assert!(p.at(MATCH_KW)); | 125 | assert!(p.at(MATCH_KW)); |
124 | let m = p.start(); | 126 | let m = p.start(); |
125 | p.bump(); | 127 | p.bump(); |
126 | expr(p); | 128 | expr_no_struct(p); |
127 | p.eat(L_CURLY); | 129 | p.eat(L_CURLY); |
128 | while !p.at(EOF) && !p.at(R_CURLY) { | 130 | while !p.at(EOF) && !p.at(R_CURLY) { |
129 | match_arm(p); | 131 | match_arm(p); |
diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs index f2b0c36f5..cedbc235f 100644 --- a/src/grammar/expressions/mod.rs +++ b/src/grammar/expressions/mod.rs | |||
@@ -6,7 +6,13 @@ pub(super) use self::atom::literal; | |||
6 | const EXPR_FIRST: TokenSet = UNARY_EXPR_FIRST; | 6 | const EXPR_FIRST: TokenSet = UNARY_EXPR_FIRST; |
7 | 7 | ||
8 | pub(super) fn expr(p: &mut Parser) { | 8 | pub(super) fn expr(p: &mut Parser) { |
9 | expr_bp(p, 1) | 9 | let r = Restrictions { forbid_structs: false }; |
10 | expr_bp(p, r, 1) | ||
11 | } | ||
12 | |||
13 | fn expr_no_struct(p: &mut Parser) { | ||
14 | let r = Restrictions { forbid_structs: true }; | ||
15 | expr_bp(p, r, 1) | ||
10 | } | 16 | } |
11 | 17 | ||
12 | // test block | 18 | // test block |
@@ -22,6 +28,11 @@ pub(super) fn block(p: &mut Parser) { | |||
22 | atom::block_expr(p); | 28 | atom::block_expr(p); |
23 | } | 29 | } |
24 | 30 | ||
31 | #[derive(Clone, Copy)] | ||
32 | struct Restrictions { | ||
33 | forbid_structs: bool | ||
34 | } | ||
35 | |||
25 | // test expr_binding_power | 36 | // test expr_binding_power |
26 | // fn foo() { | 37 | // fn foo() { |
27 | // 1 + 2 * 3 == 1 * 2 + 3 | 38 | // 1 + 2 * 3 == 1 * 2 + 3 |
@@ -36,8 +47,8 @@ fn bp_of(op: SyntaxKind) -> u8 { | |||
36 | } | 47 | } |
37 | 48 | ||
38 | // Parses expression with binding power of at least bp. | 49 | // Parses expression with binding power of at least bp. |
39 | fn expr_bp(p: &mut Parser, bp: u8) { | 50 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { |
40 | let mut lhs = match unary_expr(p) { | 51 | let mut lhs = match unary_expr(p, r) { |
41 | Some(lhs) => lhs, | 52 | Some(lhs) => lhs, |
42 | None => return, | 53 | None => return, |
43 | }; | 54 | }; |
@@ -47,7 +58,7 @@ fn expr_bp(p: &mut Parser, bp: u8) { | |||
47 | if op_bp < bp { | 58 | if op_bp < bp { |
48 | break; | 59 | break; |
49 | } | 60 | } |
50 | lhs = bin_expr(p, lhs, op_bp); | 61 | lhs = bin_expr(p, r, lhs, op_bp); |
51 | } | 62 | } |
52 | } | 63 | } |
53 | 64 | ||
@@ -57,17 +68,46 @@ const UNARY_EXPR_FIRST: TokenSet = | |||
57 | atom::ATOM_EXPR_FIRST, | 68 | atom::ATOM_EXPR_FIRST, |
58 | ]; | 69 | ]; |
59 | 70 | ||
60 | fn unary_expr(p: &mut Parser) -> Option<CompletedMarker> { | 71 | fn unary_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { |
61 | let done = match p.current() { | 72 | let m; |
62 | AMPERSAND => ref_expr(p), | 73 | let kind = match p.current() { |
63 | STAR => deref_expr(p), | 74 | // test ref_expr |
64 | EXCL => not_expr(p), | 75 | // fn foo() { |
76 | // let _ = &1; | ||
77 | // let _ = &mut &f(); | ||
78 | // } | ||
79 | AMPERSAND => { | ||
80 | m = p.start(); | ||
81 | p.bump(); | ||
82 | p.eat(MUT_KW); | ||
83 | REF_EXPR | ||
84 | |||
85 | }, | ||
86 | // test deref_expr | ||
87 | // fn foo() { | ||
88 | // **&1; | ||
89 | // } | ||
90 | STAR => { | ||
91 | m = p.start(); | ||
92 | p.bump(); | ||
93 | DEREF_EXPR | ||
94 | }, | ||
95 | // test not_expr | ||
96 | // fn foo() { | ||
97 | // !!true; | ||
98 | // } | ||
99 | EXCL => { | ||
100 | m = p.start(); | ||
101 | p.bump(); | ||
102 | NOT_EXPR | ||
103 | }, | ||
65 | _ => { | 104 | _ => { |
66 | let lhs = atom::atom_expr(p)?; | 105 | let lhs = atom::atom_expr(p, r)?; |
67 | postfix_expr(p, lhs) | 106 | return Some(postfix_expr(p, lhs)) |
68 | } | 107 | } |
69 | }; | 108 | }; |
70 | Some(done) | 109 | expr(p); |
110 | Some(m.complete(p, kind)) | ||
71 | } | 111 | } |
72 | 112 | ||
73 | fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { | 113 | fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { |
@@ -87,44 +127,6 @@ fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { | |||
87 | lhs | 127 | lhs |
88 | } | 128 | } |
89 | 129 | ||
90 | // test ref_expr | ||
91 | // fn foo() { | ||
92 | // let _ = &1; | ||
93 | // let _ = &mut &f(); | ||
94 | // } | ||
95 | fn 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 | // } | ||
108 | fn 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 | // } | ||
120 | fn 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 | 130 | // test call_expr |
129 | // fn foo() { | 131 | // fn foo() { |
130 | // let _ = f(); | 132 | // let _ = f(); |
@@ -199,11 +201,11 @@ fn arg_list(p: &mut Parser) { | |||
199 | // let _ = a::b; | 201 | // let _ = a::b; |
200 | // let _ = ::a::<b>; | 202 | // let _ = ::a::<b>; |
201 | // } | 203 | // } |
202 | fn path_expr(p: &mut Parser) -> CompletedMarker { | 204 | fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { |
203 | assert!(paths::is_path_start(p)); | 205 | assert!(paths::is_path_start(p)); |
204 | let m = p.start(); | 206 | let m = p.start(); |
205 | paths::expr_path(p); | 207 | paths::expr_path(p); |
206 | if p.at(L_CURLY) { | 208 | if p.at(L_CURLY) && !r.forbid_structs { |
207 | struct_lit(p); | 209 | struct_lit(p); |
208 | m.complete(p, STRUCT_LIT) | 210 | m.complete(p, STRUCT_LIT) |
209 | } else { | 211 | } else { |
@@ -243,13 +245,13 @@ fn struct_lit(p: &mut Parser) { | |||
243 | p.expect(R_CURLY); | 245 | p.expect(R_CURLY); |
244 | } | 246 | } |
245 | 247 | ||
246 | fn bin_expr(p: &mut Parser, lhs: CompletedMarker, bp: u8) -> CompletedMarker { | 248 | fn bin_expr(p: &mut Parser, r: Restrictions, lhs: CompletedMarker, bp: u8) -> CompletedMarker { |
247 | assert!(match p.current() { | 249 | assert!(match p.current() { |
248 | MINUS | PLUS | STAR | SLASH | EQEQ | NEQ => true, | 250 | MINUS | PLUS | STAR | SLASH | EQEQ | NEQ => true, |
249 | _ => false, | 251 | _ => false, |
250 | }); | 252 | }); |
251 | let m = lhs.precede(p); | 253 | let m = lhs.precede(p); |
252 | p.bump(); | 254 | p.bump(); |
253 | expr_bp(p, bp); | 255 | expr_bp(p, r, bp); |
254 | m.complete(p, BIN_EXPR) | 256 | m.complete(p, BIN_EXPR) |
255 | } | 257 | } |