diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-20 13:50:29 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-20 13:50:29 +0000 |
commit | 96899f8278b787280bd07d9ac9dce29a610ce40d (patch) | |
tree | d02a22f02908fd3c89e50845a06a89b997220fc2 /crates/ra_syntax/src/parsing/grammar/patterns.rs | |
parent | 5b617e3bf8252887a3eb1ce76d4b62cbee74e551 (diff) | |
parent | 86a67dce25f11ba9803a5727f77c02fd1f49e2c0 (diff) |
Merge #861
861: Move parsing to a separate module r=matklad a=matklad
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_syntax/src/parsing/grammar/patterns.rs')
-rw-r--r-- | crates/ra_syntax/src/parsing/grammar/patterns.rs | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/parsing/grammar/patterns.rs b/crates/ra_syntax/src/parsing/grammar/patterns.rs new file mode 100644 index 000000000..9d7da639d --- /dev/null +++ b/crates/ra_syntax/src/parsing/grammar/patterns.rs | |||
@@ -0,0 +1,248 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST | ||
4 | .union(paths::PATH_FIRST) | ||
5 | .union(token_set![REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE]); | ||
6 | |||
7 | pub(super) fn pattern(p: &mut Parser) { | ||
8 | pattern_r(p, PAT_RECOVERY_SET) | ||
9 | } | ||
10 | |||
11 | pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { | ||
12 | if let Some(lhs) = atom_pat(p, recovery_set) { | ||
13 | // test range_pat | ||
14 | // fn main() { | ||
15 | // match 92 { | ||
16 | // 0 ... 100 => (), | ||
17 | // 101 ..= 200 => (), | ||
18 | // 200 .. 301=> (), | ||
19 | // } | ||
20 | // } | ||
21 | if p.at(DOTDOTDOT) || p.at(DOTDOTEQ) || p.at(DOTDOT) { | ||
22 | let m = lhs.precede(p); | ||
23 | p.bump(); | ||
24 | atom_pat(p, recovery_set); | ||
25 | m.complete(p, RANGE_PAT); | ||
26 | } | ||
27 | } | ||
28 | } | ||
29 | |||
30 | const PAT_RECOVERY_SET: TokenSet = | ||
31 | token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA]; | ||
32 | |||
33 | fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { | ||
34 | let la0 = p.nth(0); | ||
35 | let la1 = p.nth(1); | ||
36 | if la0 == REF_KW | ||
37 | || la0 == MUT_KW | ||
38 | || (la0 == IDENT && !(la1 == COLONCOLON || la1 == L_PAREN || la1 == L_CURLY)) | ||
39 | { | ||
40 | return Some(bind_pat(p, true)); | ||
41 | } | ||
42 | if paths::is_path_start(p) { | ||
43 | return Some(path_pat(p)); | ||
44 | } | ||
45 | |||
46 | if is_literal_pat_start(p) { | ||
47 | return Some(literal_pat(p)); | ||
48 | } | ||
49 | |||
50 | let m = match la0 { | ||
51 | UNDERSCORE => placeholder_pat(p), | ||
52 | AMP => ref_pat(p), | ||
53 | L_PAREN => tuple_pat(p), | ||
54 | L_BRACK => slice_pat(p), | ||
55 | _ => { | ||
56 | p.err_recover("expected pattern", recovery_set); | ||
57 | return None; | ||
58 | } | ||
59 | }; | ||
60 | Some(m) | ||
61 | } | ||
62 | |||
63 | fn is_literal_pat_start(p: &mut Parser) -> bool { | ||
64 | p.at(MINUS) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER) | ||
65 | || p.at_ts(expressions::LITERAL_FIRST) | ||
66 | } | ||
67 | |||
68 | // test literal_pattern | ||
69 | // fn main() { | ||
70 | // match () { | ||
71 | // -1 => (), | ||
72 | // 92 => (), | ||
73 | // 'c' => (), | ||
74 | // "hello" => (), | ||
75 | // } | ||
76 | // } | ||
77 | fn literal_pat(p: &mut Parser) -> CompletedMarker { | ||
78 | assert!(is_literal_pat_start(p)); | ||
79 | let m = p.start(); | ||
80 | if p.at(MINUS) { | ||
81 | p.bump(); | ||
82 | } | ||
83 | expressions::literal(p); | ||
84 | m.complete(p, LITERAL_PAT) | ||
85 | } | ||
86 | |||
87 | // test path_part | ||
88 | // fn foo() { | ||
89 | // let foo::Bar = (); | ||
90 | // let ::Bar = (); | ||
91 | // let Bar { .. } = (); | ||
92 | // let Bar(..) = (); | ||
93 | // } | ||
94 | fn path_pat(p: &mut Parser) -> CompletedMarker { | ||
95 | assert!(paths::is_path_start(p)); | ||
96 | let m = p.start(); | ||
97 | paths::expr_path(p); | ||
98 | let kind = match p.current() { | ||
99 | L_PAREN => { | ||
100 | tuple_pat_fields(p); | ||
101 | TUPLE_STRUCT_PAT | ||
102 | } | ||
103 | L_CURLY => { | ||
104 | field_pat_list(p); | ||
105 | STRUCT_PAT | ||
106 | } | ||
107 | _ => PATH_PAT, | ||
108 | }; | ||
109 | m.complete(p, kind) | ||
110 | } | ||
111 | |||
112 | // test tuple_pat_fields | ||
113 | // fn foo() { | ||
114 | // let S() = (); | ||
115 | // let S(_) = (); | ||
116 | // let S(_,) = (); | ||
117 | // let S(_, .. , x) = (); | ||
118 | // } | ||
119 | fn tuple_pat_fields(p: &mut Parser) { | ||
120 | assert!(p.at(L_PAREN)); | ||
121 | p.bump(); | ||
122 | pat_list(p, R_PAREN); | ||
123 | p.expect(R_PAREN); | ||
124 | } | ||
125 | |||
126 | // test field_pat_list | ||
127 | // fn foo() { | ||
128 | // let S {} = (); | ||
129 | // let S { f, ref mut g } = (); | ||
130 | // let S { h: _, ..} = (); | ||
131 | // let S { h: _, } = (); | ||
132 | // } | ||
133 | fn field_pat_list(p: &mut Parser) { | ||
134 | assert!(p.at(L_CURLY)); | ||
135 | let m = p.start(); | ||
136 | p.bump(); | ||
137 | while !p.at(EOF) && !p.at(R_CURLY) { | ||
138 | match p.current() { | ||
139 | DOTDOT => p.bump(), | ||
140 | IDENT if p.nth(1) == COLON => field_pat(p), | ||
141 | L_CURLY => error_block(p, "expected ident"), | ||
142 | _ => { | ||
143 | bind_pat(p, false); | ||
144 | } | ||
145 | } | ||
146 | if !p.at(R_CURLY) { | ||
147 | p.expect(COMMA); | ||
148 | } | ||
149 | } | ||
150 | p.expect(R_CURLY); | ||
151 | m.complete(p, FIELD_PAT_LIST); | ||
152 | } | ||
153 | |||
154 | fn field_pat(p: &mut Parser) { | ||
155 | assert!(p.at(IDENT)); | ||
156 | assert!(p.nth(1) == COLON); | ||
157 | |||
158 | let m = p.start(); | ||
159 | name(p); | ||
160 | p.bump(); | ||
161 | pattern(p); | ||
162 | m.complete(p, FIELD_PAT); | ||
163 | } | ||
164 | |||
165 | // test placeholder_pat | ||
166 | // fn main() { let _ = (); } | ||
167 | fn placeholder_pat(p: &mut Parser) -> CompletedMarker { | ||
168 | assert!(p.at(UNDERSCORE)); | ||
169 | let m = p.start(); | ||
170 | p.bump(); | ||
171 | m.complete(p, PLACEHOLDER_PAT) | ||
172 | } | ||
173 | |||
174 | // test ref_pat | ||
175 | // fn main() { | ||
176 | // let &a = (); | ||
177 | // let &mut b = (); | ||
178 | // } | ||
179 | fn ref_pat(p: &mut Parser) -> CompletedMarker { | ||
180 | assert!(p.at(AMP)); | ||
181 | let m = p.start(); | ||
182 | p.bump(); | ||
183 | p.eat(MUT_KW); | ||
184 | pattern(p); | ||
185 | m.complete(p, REF_PAT) | ||
186 | } | ||
187 | |||
188 | // test tuple_pat | ||
189 | // fn main() { | ||
190 | // let (a, b, ..) = (); | ||
191 | // } | ||
192 | fn tuple_pat(p: &mut Parser) -> CompletedMarker { | ||
193 | assert!(p.at(L_PAREN)); | ||
194 | let m = p.start(); | ||
195 | tuple_pat_fields(p); | ||
196 | m.complete(p, TUPLE_PAT) | ||
197 | } | ||
198 | |||
199 | // test slice_pat | ||
200 | // fn main() { | ||
201 | // let [a, b, ..] = []; | ||
202 | // } | ||
203 | fn slice_pat(p: &mut Parser) -> CompletedMarker { | ||
204 | assert!(p.at(L_BRACK)); | ||
205 | let m = p.start(); | ||
206 | p.bump(); | ||
207 | pat_list(p, R_BRACK); | ||
208 | p.expect(R_BRACK); | ||
209 | m.complete(p, SLICE_PAT) | ||
210 | } | ||
211 | |||
212 | fn pat_list(p: &mut Parser, ket: SyntaxKind) { | ||
213 | while !p.at(EOF) && !p.at(ket) { | ||
214 | match p.current() { | ||
215 | DOTDOT => p.bump(), | ||
216 | _ => { | ||
217 | if !p.at_ts(PATTERN_FIRST) { | ||
218 | p.error("expected a pattern"); | ||
219 | break; | ||
220 | } | ||
221 | pattern(p) | ||
222 | } | ||
223 | } | ||
224 | if !p.at(ket) { | ||
225 | p.expect(COMMA); | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | // test bind_pat | ||
231 | // fn main() { | ||
232 | // let a = (); | ||
233 | // let mut b = (); | ||
234 | // let ref c = (); | ||
235 | // let ref mut d = (); | ||
236 | // let e @ _ = (); | ||
237 | // let ref mut f @ g @ _ = (); | ||
238 | // } | ||
239 | fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker { | ||
240 | let m = p.start(); | ||
241 | p.eat(REF_KW); | ||
242 | p.eat(MUT_KW); | ||
243 | name(p); | ||
244 | if with_at && p.eat(AT) { | ||
245 | pattern(p); | ||
246 | } | ||
247 | m.complete(p, BIND_PAT) | ||
248 | } | ||