1 //! FIXME: write short doc here
5 pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST
6 .union(paths::PATH_FIRST)
7 .union(token_set![T![box], T![ref], T![mut], T!['('], T!['['], T![&], T![_], T![-], T![.]]);
9 pub(crate) fn pattern(p: &mut Parser) {
10 pattern_r(p, PAT_RECOVERY_SET);
13 /// Parses a pattern list separated by pipes `|`
14 pub(super) fn pattern_top(p: &mut Parser) {
15 pattern_top_r(p, PAT_RECOVERY_SET)
18 pub(crate) fn pattern_single(p: &mut Parser) {
19 pattern_single_r(p, PAT_RECOVERY_SET);
22 /// Parses a pattern list separated by pipes `|`
23 /// using the given `recovery_set`
24 pub(super) fn pattern_top_r(p: &mut Parser, recovery_set: TokenSet) {
26 pattern_r(p, recovery_set);
29 /// Parses a pattern list separated by pipes `|`, with no leading `|`,using the
30 /// given `recovery_set`
40 fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
42 pattern_single_r(p, recovery_set);
49 pattern_single_r(p, recovery_set);
51 m.complete(p, OR_PAT);
54 fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) {
55 if let Some(lhs) = atom_pat(p, recovery_set) {
64 for &range_op in [T![...], T![..=], T![..]].iter() {
66 let m = lhs.precede(p);
68 atom_pat(p, recovery_set);
69 m.complete(p, RANGE_PAT);
76 const PAT_RECOVERY_SET: TokenSet =
77 token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA];
79 fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
80 let m = match p.nth(0) {
81 T![box] => box_pat(p),
82 T![ref] | T![mut] => ident_pat(p, true),
83 IDENT => match p.nth(1) {
84 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
86 T!['('] | T!['{'] | T![!] => path_or_macro_pat(p),
87 T![:] if p.nth_at(1, T![::]) => path_or_macro_pat(p),
88 _ => ident_pat(p, true),
91 // test type_path_in_pattern
92 // fn main() { let <_>::Foo = (); }
93 _ if paths::is_path_start(p) => path_or_macro_pat(p),
94 _ if is_literal_pat_start(p) => literal_pat(p),
96 T![.] if p.at(T![..]) => rest_pat(p),
97 T![_] => wildcard_pat(p),
99 T!['('] => tuple_pat(p),
100 T!['['] => slice_pat(p),
103 p.err_recover("expected pattern", recovery_set);
111 fn is_literal_pat_start(p: &Parser) -> bool {
112 p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER)
113 || p.at_ts(expressions::LITERAL_FIRST)
116 // test literal_pattern
125 fn literal_pat(p: &mut Parser) -> CompletedMarker {
126 assert!(is_literal_pat_start(p));
131 expressions::literal(p);
132 m.complete(p, LITERAL_PAT)
137 // let foo::Bar = ();
139 // let Bar { .. } = ();
142 fn path_or_macro_pat(p: &mut Parser) -> CompletedMarker {
143 assert!(paths::is_path_start(p));
146 let kind = match p.current() {
152 record_pat_field_list(p);
160 items::macro_call_after_excl(p);
161 return m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_PAT);
168 // test tuple_pat_fields
173 // let S(_, .. , x) = ();
175 fn tuple_pat_fields(p: &mut Parser) {
176 assert!(p.at(T!['(']));
178 pat_list(p, T![')']);
182 // test record_field_pat_list
185 // let S { f, ref mut g } = ();
186 // let S { h: _, ..} = ();
187 // let S { h: _, } = ();
189 fn record_pat_field_list(p: &mut Parser) {
190 assert!(p.at(T!['{']));
193 while !p.at(EOF) && !p.at(T!['}']) {
195 // A trailing `..` is *not* treated as a REST_PAT.
196 T![.] if p.at(T![..]) => p.bump(T![..]),
197 T!['{'] => error_block(p, "expected ident"),
202 // test record_field_pat
204 // let S { 0: 1 } = ();
205 // let S { x: 1 } = ();
207 IDENT | INT_NUMBER if p.nth(1) == T![:] => {
208 name_ref_or_index(p);
213 // FIXME: not all box patterns should be allowed
220 m.complete(p, RECORD_PAT_FIELD);
228 m.complete(p, RECORD_PAT_FIELD_LIST);
231 // test placeholder_pat
232 // fn main() { let _ = (); }
233 fn wildcard_pat(p: &mut Parser) -> CompletedMarker {
234 assert!(p.at(T![_]));
237 m.complete(p, WILDCARD_PAT)
247 // let (a, ..,) = ();
248 // let Tuple(a, ..) = ();
249 // let Tuple(a, ..,) = ();
250 // let (.., ..) = ();
251 // let Tuple(.., ..) = ();
252 // let (.., a, ..) = ();
253 // let Tuple(.., a, ..) = ();
258 // let [head, ..] = ();
259 // let [head, tail @ ..] = ();
260 // let [head, .., cons] = ();
261 // let [head, mid @ .., cons] = ();
262 // let [head, .., .., cons] = ();
263 // let [head, .., mid, tail @ ..] = ();
264 // let [head, .., mid, .., cons] = ();
266 fn rest_pat(p: &mut Parser) -> CompletedMarker {
267 assert!(p.at(T![..]));
270 m.complete(p, REST_PAT)
278 fn ref_pat(p: &mut Parser) -> CompletedMarker {
279 assert!(p.at(T![&]));
284 m.complete(p, REF_PAT)
289 // let (a, b, ..) = ();
294 fn tuple_pat(p: &mut Parser) -> CompletedMarker {
295 assert!(p.at(T!['(']));
298 let mut has_comma = false;
299 let mut has_pat = false;
300 let mut has_rest = false;
301 while !p.at(EOF) && !p.at(T![')']) {
303 if !p.at_ts(PATTERN_FIRST) {
304 p.error("expected a pattern");
307 has_rest |= p.at(T![..]);
317 m.complete(p, if !has_comma && !has_rest && has_pat { PAREN_PAT } else { TUPLE_PAT })
322 // let [a, b, ..] = [];
324 fn slice_pat(p: &mut Parser) -> CompletedMarker {
325 assert!(p.at(T!['[']));
328 pat_list(p, T![']']);
330 m.complete(p, SLICE_PAT)
333 fn pat_list(p: &mut Parser, ket: SyntaxKind) {
334 while !p.at(EOF) && !p.at(ket) {
335 if !p.at_ts(PATTERN_FIRST) {
336 p.error("expected a pattern");
352 // let ref mut d = ();
354 // let ref mut f @ g @ _ = ();
356 fn ident_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
361 if with_at && p.eat(T![@]) {
364 m.complete(p, IDENT_PAT)
370 // let box Outer { box i, j: box Inner(box &x) } = ();
371 // let box ref mut i = ();
373 fn box_pat(p: &mut Parser) -> CompletedMarker {
374 assert!(p.at(T![box]));
378 m.complete(p, BOX_PAT)