1 //! FIXME: write short doc here
5 pub(super) const PATTERN_FIRST: TokenSet =
6 expressions::LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[
18 pub(crate) fn pattern(p: &mut Parser) {
19 pattern_r(p, PAT_RECOVERY_SET);
22 /// Parses a pattern list separated by pipes `|`
23 pub(super) fn pattern_top(p: &mut Parser) {
24 pattern_top_r(p, PAT_RECOVERY_SET)
27 pub(crate) fn pattern_single(p: &mut Parser) {
28 pattern_single_r(p, PAT_RECOVERY_SET);
31 /// Parses a pattern list separated by pipes `|`
32 /// using the given `recovery_set`
33 pub(super) fn pattern_top_r(p: &mut Parser, recovery_set: TokenSet) {
35 pattern_r(p, recovery_set);
38 /// Parses a pattern list separated by pipes `|`, with no leading `|`,using the
39 /// given `recovery_set`
49 fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
51 pattern_single_r(p, recovery_set);
58 pattern_single_r(p, recovery_set);
60 m.complete(p, OR_PAT);
63 fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) {
64 if let Some(lhs) = atom_pat(p, recovery_set) {
73 for &range_op in [T![...], T![..=], T![..]].iter() {
75 let m = lhs.precede(p);
77 atom_pat(p, recovery_set);
78 m.complete(p, RANGE_PAT);
85 const PAT_RECOVERY_SET: TokenSet =
86 TokenSet::new(&[LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA]);
88 fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
89 let m = match p.nth(0) {
90 T![box] => box_pat(p),
91 T![ref] | T![mut] => ident_pat(p, true),
92 T![const] => const_block_pat(p),
93 IDENT => match p.nth(1) {
94 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
96 T!['('] | T!['{'] | T![!] => path_or_macro_pat(p),
97 T![:] if p.nth_at(1, T![::]) => path_or_macro_pat(p),
98 _ => ident_pat(p, true),
101 // test type_path_in_pattern
102 // fn main() { let <_>::Foo = (); }
103 _ if paths::is_path_start(p) => path_or_macro_pat(p),
104 _ if is_literal_pat_start(p) => literal_pat(p),
106 T![.] if p.at(T![..]) => rest_pat(p),
107 T![_] => wildcard_pat(p),
109 T!['('] => tuple_pat(p),
110 T!['['] => slice_pat(p),
113 p.err_recover("expected pattern", recovery_set);
121 fn is_literal_pat_start(p: &Parser) -> bool {
122 p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER)
123 || p.at_ts(expressions::LITERAL_FIRST)
126 // test literal_pattern
135 fn literal_pat(p: &mut Parser) -> CompletedMarker {
136 assert!(is_literal_pat_start(p));
141 expressions::literal(p);
142 m.complete(p, LITERAL_PAT)
147 // let foo::Bar = ();
149 // let Bar { .. } = ();
152 fn path_or_macro_pat(p: &mut Parser) -> CompletedMarker {
153 assert!(paths::is_path_start(p));
156 let kind = match p.current() {
162 record_pat_field_list(p);
170 items::macro_call_after_excl(p);
171 return m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_PAT);
178 // test tuple_pat_fields
183 // let S(_, .. , x) = ();
185 fn tuple_pat_fields(p: &mut Parser) {
186 assert!(p.at(T!['(']));
188 pat_list(p, T![')']);
192 // test record_pat_field_list
195 // let S { f, ref mut g } = ();
196 // let S { h: _, ..} = ();
197 // let S { h: _, } = ();
199 fn record_pat_field_list(p: &mut Parser) {
200 assert!(p.at(T!['{']));
203 while !p.at(EOF) && !p.at(T!['}']) {
205 // A trailing `..` is *not* treated as a REST_PAT.
206 T![.] if p.at(T![..]) => p.bump(T![..]),
207 T!['{'] => error_block(p, "expected ident"),
212 // test record_pat_field
214 // let S { 0: 1 } = ();
215 // let S { x: 1 } = ();
217 IDENT | INT_NUMBER if p.nth(1) == T![:] => {
218 name_ref_or_index(p);
223 // FIXME: not all box patterns should be allowed
230 m.complete(p, RECORD_PAT_FIELD);
238 m.complete(p, RECORD_PAT_FIELD_LIST);
241 // test placeholder_pat
242 // fn main() { let _ = (); }
243 fn wildcard_pat(p: &mut Parser) -> CompletedMarker {
244 assert!(p.at(T![_]));
247 m.complete(p, WILDCARD_PAT)
257 // let (a, ..,) = ();
258 // let Tuple(a, ..) = ();
259 // let Tuple(a, ..,) = ();
260 // let (.., ..) = ();
261 // let Tuple(.., ..) = ();
262 // let (.., a, ..) = ();
263 // let Tuple(.., a, ..) = ();
268 // let [head, ..] = ();
269 // let [head, tail @ ..] = ();
270 // let [head, .., cons] = ();
271 // let [head, mid @ .., cons] = ();
272 // let [head, .., .., cons] = ();
273 // let [head, .., mid, tail @ ..] = ();
274 // let [head, .., mid, .., cons] = ();
276 fn rest_pat(p: &mut Parser) -> CompletedMarker {
277 assert!(p.at(T![..]));
280 m.complete(p, REST_PAT)
288 fn ref_pat(p: &mut Parser) -> CompletedMarker {
289 assert!(p.at(T![&]));
294 m.complete(p, REF_PAT)
299 // let (a, b, ..) = ();
304 fn tuple_pat(p: &mut Parser) -> CompletedMarker {
305 assert!(p.at(T!['(']));
308 let mut has_comma = false;
309 let mut has_pat = false;
310 let mut has_rest = false;
311 while !p.at(EOF) && !p.at(T![')']) {
313 if !p.at_ts(PATTERN_FIRST) {
314 p.error("expected a pattern");
317 has_rest |= p.at(T![..]);
327 m.complete(p, if !has_comma && !has_rest && has_pat { PAREN_PAT } else { TUPLE_PAT })
332 // let [a, b, ..] = [];
334 fn slice_pat(p: &mut Parser) -> CompletedMarker {
335 assert!(p.at(T!['[']));
338 pat_list(p, T![']']);
340 m.complete(p, SLICE_PAT)
343 fn pat_list(p: &mut Parser, ket: SyntaxKind) {
344 while !p.at(EOF) && !p.at(ket) {
345 if !p.at_ts(PATTERN_FIRST) {
346 p.error("expected a pattern");
362 // let ref mut d = ();
364 // let ref mut f @ g @ _ = ();
366 fn ident_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
371 if with_at && p.eat(T![@]) {
374 m.complete(p, IDENT_PAT)
380 // let box Outer { box i, j: box Inner(box &x) } = ();
381 // let box ref mut i = ();
383 fn box_pat(p: &mut Parser) -> CompletedMarker {
384 assert!(p.at(T![box]));
388 m.complete(p, BOX_PAT)
391 // test const_block_pat
393 // let const { 15 } = ();
394 // let const { foo(); bar() } = ();
396 fn const_block_pat(p: &mut Parser) -> CompletedMarker {
397 assert!(p.at(T![const]));
400 expressions::block_expr(p);
401 m.complete(p, CONST_BLOCK_PAT)