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 IDENT => match p.nth(1) {
93 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
95 T!['('] | T!['{'] | T![!] => path_or_macro_pat(p),
96 T![:] if p.nth_at(1, T![::]) => path_or_macro_pat(p),
97 _ => ident_pat(p, true),
100 // test type_path_in_pattern
101 // fn main() { let <_>::Foo = (); }
102 _ if paths::is_path_start(p) => path_or_macro_pat(p),
103 _ if is_literal_pat_start(p) => literal_pat(p),
105 T![.] if p.at(T![..]) => rest_pat(p),
106 T![_] => wildcard_pat(p),
108 T!['('] => tuple_pat(p),
109 T!['['] => slice_pat(p),
112 p.err_recover("expected pattern", recovery_set);
120 fn is_literal_pat_start(p: &Parser) -> bool {
121 p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER)
122 || p.at_ts(expressions::LITERAL_FIRST)
125 // test literal_pattern
134 fn literal_pat(p: &mut Parser) -> CompletedMarker {
135 assert!(is_literal_pat_start(p));
140 expressions::literal(p);
141 m.complete(p, LITERAL_PAT)
146 // let foo::Bar = ();
148 // let Bar { .. } = ();
151 fn path_or_macro_pat(p: &mut Parser) -> CompletedMarker {
152 assert!(paths::is_path_start(p));
155 let kind = match p.current() {
161 record_pat_field_list(p);
169 items::macro_call_after_excl(p);
170 return m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_PAT);
177 // test tuple_pat_fields
182 // let S(_, .. , x) = ();
184 fn tuple_pat_fields(p: &mut Parser) {
185 assert!(p.at(T!['(']));
187 pat_list(p, T![')']);
191 // test record_pat_field_list
194 // let S { f, ref mut g } = ();
195 // let S { h: _, ..} = ();
196 // let S { h: _, } = ();
198 fn record_pat_field_list(p: &mut Parser) {
199 assert!(p.at(T!['{']));
202 while !p.at(EOF) && !p.at(T!['}']) {
204 // A trailing `..` is *not* treated as a REST_PAT.
205 T![.] if p.at(T![..]) => p.bump(T![..]),
206 T!['{'] => error_block(p, "expected ident"),
211 // test record_pat_field
213 // let S { 0: 1 } = ();
214 // let S { x: 1 } = ();
216 IDENT | INT_NUMBER if p.nth(1) == T![:] => {
217 name_ref_or_index(p);
222 // FIXME: not all box patterns should be allowed
229 m.complete(p, RECORD_PAT_FIELD);
237 m.complete(p, RECORD_PAT_FIELD_LIST);
240 // test placeholder_pat
241 // fn main() { let _ = (); }
242 fn wildcard_pat(p: &mut Parser) -> CompletedMarker {
243 assert!(p.at(T![_]));
246 m.complete(p, WILDCARD_PAT)
256 // let (a, ..,) = ();
257 // let Tuple(a, ..) = ();
258 // let Tuple(a, ..,) = ();
259 // let (.., ..) = ();
260 // let Tuple(.., ..) = ();
261 // let (.., a, ..) = ();
262 // let Tuple(.., a, ..) = ();
267 // let [head, ..] = ();
268 // let [head, tail @ ..] = ();
269 // let [head, .., cons] = ();
270 // let [head, mid @ .., cons] = ();
271 // let [head, .., .., cons] = ();
272 // let [head, .., mid, tail @ ..] = ();
273 // let [head, .., mid, .., cons] = ();
275 fn rest_pat(p: &mut Parser) -> CompletedMarker {
276 assert!(p.at(T![..]));
279 m.complete(p, REST_PAT)
287 fn ref_pat(p: &mut Parser) -> CompletedMarker {
288 assert!(p.at(T![&]));
293 m.complete(p, REF_PAT)
298 // let (a, b, ..) = ();
303 fn tuple_pat(p: &mut Parser) -> CompletedMarker {
304 assert!(p.at(T!['(']));
307 let mut has_comma = false;
308 let mut has_pat = false;
309 let mut has_rest = false;
310 while !p.at(EOF) && !p.at(T![')']) {
312 if !p.at_ts(PATTERN_FIRST) {
313 p.error("expected a pattern");
316 has_rest |= p.at(T![..]);
326 m.complete(p, if !has_comma && !has_rest && has_pat { PAREN_PAT } else { TUPLE_PAT })
331 // let [a, b, ..] = [];
333 fn slice_pat(p: &mut Parser) -> CompletedMarker {
334 assert!(p.at(T!['[']));
337 pat_list(p, T![']']);
339 m.complete(p, SLICE_PAT)
342 fn pat_list(p: &mut Parser, ket: SyntaxKind) {
343 while !p.at(EOF) && !p.at(ket) {
344 if !p.at_ts(PATTERN_FIRST) {
345 p.error("expected a pattern");
361 // let ref mut d = ();
363 // let ref mut f @ g @ _ = ();
365 fn ident_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
370 if with_at && p.eat(T![@]) {
373 m.complete(p, IDENT_PAT)
379 // let box Outer { box i, j: box Inner(box &x) } = ();
380 // let box ref mut i = ();
382 fn box_pat(p: &mut Parser) -> CompletedMarker {
383 assert!(p.at(T![box]));
387 m.complete(p, BOX_PAT)