diff options
Diffstat (limited to 'src/grammar/patterns.rs')
-rw-r--r-- | src/grammar/patterns.rs | 92 |
1 files changed, 88 insertions, 4 deletions
diff --git a/src/grammar/patterns.rs b/src/grammar/patterns.rs index 7216807fd..770274686 100644 --- a/src/grammar/patterns.rs +++ b/src/grammar/patterns.rs | |||
@@ -1,14 +1,98 @@ | |||
1 | use super::*; | 1 | use super::*; |
2 | 2 | ||
3 | pub(super) fn pattern(p: &mut Parser) { | 3 | pub(super) fn pattern(p: &mut Parser) { |
4 | match p.current() { | 4 | let la0 = p.nth(0); |
5 | let la1 = p.nth(1); | ||
6 | if la0 == REF_KW || la0 == MUT_KW | ||
7 | || (la0 == IDENT && !(la1 == COLONCOLON || la1 == L_PAREN || la1 == L_CURLY)) { | ||
8 | bind_pat(p, true); | ||
9 | return; | ||
10 | } | ||
11 | if paths::is_path_start(p) { | ||
12 | path_pat(p); | ||
13 | return; | ||
14 | } | ||
15 | |||
16 | match la0 { | ||
5 | UNDERSCORE => placeholder_pat(p), | 17 | UNDERSCORE => placeholder_pat(p), |
6 | AMPERSAND => ref_pat(p), | 18 | AMPERSAND => ref_pat(p), |
7 | IDENT | REF_KW | MUT_KW => bind_pat(p), | ||
8 | _ => p.err_and_bump("expected pattern"), | 19 | _ => p.err_and_bump("expected pattern"), |
9 | } | 20 | } |
10 | } | 21 | } |
11 | 22 | ||
23 | // test path_part | ||
24 | // fn foo() { | ||
25 | // let foo::Bar = (); | ||
26 | // let ::Bar = (); | ||
27 | // let Bar { .. } = (); | ||
28 | // let Bar(..) = (); | ||
29 | // } | ||
30 | fn path_pat(p: &mut Parser) { | ||
31 | let m = p.start(); | ||
32 | paths::expr_path(p); | ||
33 | let kind = match p.current() { | ||
34 | L_PAREN => { | ||
35 | tuple_pat_fields(p); | ||
36 | TUPLE_PAT | ||
37 | } | ||
38 | L_CURLY => { | ||
39 | struct_pat_fields(p); | ||
40 | STRUCT_PAT | ||
41 | } | ||
42 | _ => PATH_PAT | ||
43 | }; | ||
44 | m.complete(p, kind); | ||
45 | } | ||
46 | |||
47 | // test tuple_pat_fields | ||
48 | // fn foo() { | ||
49 | // let S() = (); | ||
50 | // let S(_) = (); | ||
51 | // let S(_,) = (); | ||
52 | // let S(_, .. , x) = (); | ||
53 | // } | ||
54 | fn tuple_pat_fields(p: &mut Parser) { | ||
55 | assert!(p.at(L_PAREN)); | ||
56 | p.bump(); | ||
57 | while !p.at(EOF) && !p.at(R_PAREN) { | ||
58 | match p.current() { | ||
59 | DOTDOT => p.bump(), | ||
60 | _ => pattern(p), | ||
61 | } | ||
62 | if !p.at(R_PAREN) { | ||
63 | p.expect(COMMA); | ||
64 | } | ||
65 | } | ||
66 | p.expect(R_PAREN); | ||
67 | } | ||
68 | |||
69 | // test struct_pat_fields | ||
70 | // fn foo() { | ||
71 | // let S {} = (); | ||
72 | // let S { f, ref mut g } = (); | ||
73 | // let S { h: _, ..} = (); | ||
74 | // let S { h: _, } = (); | ||
75 | // } | ||
76 | fn struct_pat_fields(p: &mut Parser) { | ||
77 | assert!(p.at(L_CURLY)); | ||
78 | p.bump(); | ||
79 | while !p.at(EOF) && !p.at(R_CURLY) { | ||
80 | match p.current() { | ||
81 | DOTDOT => p.bump(), | ||
82 | IDENT if p.nth(1) == COLON => { | ||
83 | p.bump(); | ||
84 | p.bump(); | ||
85 | pattern(p); | ||
86 | } | ||
87 | _ => bind_pat(p, false), | ||
88 | } | ||
89 | if !p.at(R_CURLY) { | ||
90 | p.expect(COMMA); | ||
91 | } | ||
92 | } | ||
93 | p.expect(R_CURLY); | ||
94 | } | ||
95 | |||
12 | // test placeholder_pat | 96 | // test placeholder_pat |
13 | // fn main() { let _ = (); } | 97 | // fn main() { let _ = (); } |
14 | fn placeholder_pat(p: &mut Parser) { | 98 | fn placeholder_pat(p: &mut Parser) { |
@@ -41,12 +125,12 @@ fn ref_pat(p: &mut Parser) { | |||
41 | // let e @ _ = (); | 125 | // let e @ _ = (); |
42 | // let ref mut f @ g @ _ = (); | 126 | // let ref mut f @ g @ _ = (); |
43 | // } | 127 | // } |
44 | fn bind_pat(p: &mut Parser) { | 128 | fn bind_pat(p: &mut Parser, with_at: bool) { |
45 | let m = p.start(); | 129 | let m = p.start(); |
46 | p.eat(REF_KW); | 130 | p.eat(REF_KW); |
47 | p.eat(MUT_KW); | 131 | p.eat(MUT_KW); |
48 | name(p); | 132 | name(p); |
49 | if p.eat(AT) { | 133 | if with_at && p.eat(AT) { |
50 | pattern(p); | 134 | pattern(p); |
51 | } | 135 | } |
52 | m.complete(p, BIND_PAT); | 136 | m.complete(p, BIND_PAT); |