aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/grammar/params.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/grammar/params.rs')
-rw-r--r--crates/ra_syntax/src/grammar/params.rs142
1 files changed, 142 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/grammar/params.rs b/crates/ra_syntax/src/grammar/params.rs
new file mode 100644
index 000000000..903c25939
--- /dev/null
+++ b/crates/ra_syntax/src/grammar/params.rs
@@ -0,0 +1,142 @@
1use super::*;
2
3// test param_list
4// fn a() {}
5// fn b(x: i32) {}
6// fn c(x: i32, ) {}
7// fn d(x: i32, y: ()) {}
8pub(super) fn param_list(p: &mut Parser) {
9 list_(p, Flavor::Normal)
10}
11
12// test param_list_opt_patterns
13// fn foo<F: FnMut(&mut Foo<'a>)>(){}
14pub(super) fn param_list_opt_patterns(p: &mut Parser) {
15 list_(p, Flavor::OptionalPattern)
16}
17
18pub(super) fn param_list_opt_types(p: &mut Parser) {
19 list_(p, Flavor::OptionalType)
20}
21
22#[derive(Clone, Copy, Eq, PartialEq)]
23enum Flavor {
24 OptionalType,
25 OptionalPattern,
26 Normal,
27}
28
29impl Flavor {
30 fn type_required(self) -> bool {
31 match self {
32 Flavor::OptionalType => false,
33 _ => true,
34 }
35 }
36}
37
38fn list_(p: &mut Parser, flavor: Flavor) {
39 let (bra, ket) = if flavor.type_required() {
40 (L_PAREN, R_PAREN)
41 } else {
42 (PIPE, PIPE)
43 };
44 assert!(p.at(bra));
45 let m = p.start();
46 p.bump();
47 if flavor.type_required() {
48 opt_self_param(p);
49 }
50 while !p.at(EOF) && !p.at(ket) {
51 if !p.at_ts(VALUE_PARAMETER_FIRST) {
52 p.error("expected value parameter");
53 break;
54 }
55 value_parameter(p, flavor);
56 if !p.at(ket) {
57 p.expect(COMMA);
58 }
59 }
60 p.expect(ket);
61 m.complete(p, PARAM_LIST);
62}
63
64
65const VALUE_PARAMETER_FIRST: TokenSet =
66 token_set_union![
67 patterns::PATTERN_FIRST,
68 types::TYPE_FIRST,
69 ];
70
71fn value_parameter(p: &mut Parser, flavor: Flavor) {
72 let m = p.start();
73 match flavor {
74 Flavor::OptionalType | Flavor::Normal => {
75 patterns::pattern(p);
76 if p.at(COLON) || flavor.type_required() {
77 types::ascription(p)
78 }
79 },
80 // test value_parameters_no_patterns
81 // type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>;
82 Flavor::OptionalPattern => {
83 let la0 = p.current();
84 let la1 = p.nth(1);
85 let la2 = p.nth(2);
86 let la3 = p.nth(3);
87 if la0 == IDENT && la1 == COLON
88 || la0 == AMP && la1 == IDENT && la2 == COLON
89 || la0 == AMP && la1 == MUT_KW && la2 == IDENT && la3 == COLON {
90 patterns::pattern(p);
91 types::ascription(p);
92 } else {
93 types::type_(p);
94 }
95 },
96 }
97 m.complete(p, PARAM);
98}
99
100// test self_param
101// impl S {
102// fn a(self) {}
103// fn b(&self,) {}
104// fn c(&'a self,) {}
105// fn d(&'a mut self, x: i32) {}
106// fn e(mut self) {}
107// }
108fn opt_self_param(p: &mut Parser) {
109 let m;
110 if p.at(SELF_KW) || p.at(MUT_KW) && p.nth(1) == SELF_KW {
111 m = p.start();
112 p.eat(MUT_KW);
113 p.eat(SELF_KW);
114 // test arb_self_types
115 // impl S {
116 // fn a(self: &Self) {}
117 // fn b(mut self: Box<Self>) {}
118 // }
119 if p.at(COLON) {
120 types::ascription(p);
121 }
122 } else {
123 let la1 = p.nth(1);
124 let la2 = p.nth(2);
125 let la3 = p.nth(3);
126 let n_toks = match (p.current(), la1, la2, la3) {
127 (AMP, SELF_KW, _, _) => 2,
128 (AMP, MUT_KW, SELF_KW, _) => 3,
129 (AMP, LIFETIME, SELF_KW, _) => 3,
130 (AMP, LIFETIME, MUT_KW, SELF_KW) => 4,
131 _ => return,
132 };
133 m = p.start();
134 for _ in 0..n_toks {
135 p.bump();
136 }
137 }
138 m.complete(p, SELF_PARAM);
139 if !p.at(R_PAREN) {
140 p.expect(COMMA);
141 }
142}