aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar
diff options
context:
space:
mode:
authorToby Dimmick <[email protected]>2020-02-06 11:44:00 +0000
committerToby Dimmick <[email protected]>2020-02-06 19:45:51 +0000
commit7e66785859fc4a31fc3faf4848174699d3a2c020 (patch)
tree94a61899b4628eeca7a21a58c061b343bcf32e62 /crates/ra_parser/src/grammar
parenta4431e83025223d5aea0ae3d49a6356775cb5f75 (diff)
Rework value parameter parsing
- `Fn__(...)` parameters with idents/patterns no longer parse - Trait function parameters with arbitrary patterns parse - Trait function parameters without idents/patterns no longer parse - `fn(...)` parameters no longer parse with patterns other than a single ident
Diffstat (limited to 'crates/ra_parser/src/grammar')
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs2
-rw-r--r--crates/ra_parser/src/grammar/items.rs9
-rw-r--r--crates/ra_parser/src/grammar/params.rs111
-rw-r--r--crates/ra_parser/src/grammar/paths.rs4
-rw-r--r--crates/ra_parser/src/grammar/types.rs2
5 files changed, 73 insertions, 55 deletions
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index 2cc321473..f154077a8 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -229,7 +229,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
229 let m = p.start(); 229 let m = p.start();
230 p.eat(T![async]); 230 p.eat(T![async]);
231 p.eat(T![move]); 231 p.eat(T![move]);
232 params::param_list_opt_types(p); 232 params::param_list_closure(p);
233 if opt_fn_ret_type(p) { 233 if opt_fn_ret_type(p) {
234 if !p.at(T!['{']) { 234 if !p.at(T!['{']) {
235 p.error("expected `{`"); 235 p.error("expected `{`");
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 6e23d9b72..b20d224e8 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -164,7 +164,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
164 // async unsafe fn foo() {} 164 // async unsafe fn foo() {}
165 // unsafe const fn bar() {} 165 // unsafe const fn bar() {}
166 T![fn] => { 166 T![fn] => {
167 fn_def(p, flavor); 167 fn_def(p);
168 m.complete(p, FN_DEF); 168 m.complete(p, FN_DEF);
169 } 169 }
170 170
@@ -301,7 +301,7 @@ pub(crate) fn extern_item_list(p: &mut Parser) {
301 m.complete(p, EXTERN_ITEM_LIST); 301 m.complete(p, EXTERN_ITEM_LIST);
302} 302}
303 303
304fn fn_def(p: &mut Parser, flavor: ItemFlavor) { 304fn fn_def(p: &mut Parser) {
305 assert!(p.at(T![fn])); 305 assert!(p.at(T![fn]));
306 p.bump(T![fn]); 306 p.bump(T![fn]);
307 307
@@ -311,10 +311,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
311 type_params::opt_type_param_list(p); 311 type_params::opt_type_param_list(p);
312 312
313 if p.at(T!['(']) { 313 if p.at(T!['(']) {
314 match flavor { 314 params::param_list_fn(p);
315 ItemFlavor::Mod => params::param_list(p),
316 ItemFlavor::Trait => params::param_list_opt_patterns(p),
317 }
318 } else { 315 } else {
319 p.error("expected function arguments"); 316 p.error("expected function arguments");
320 } 317 }
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs
index c10b53316..897092a67 100644
--- a/crates/ra_parser/src/grammar/params.rs
+++ b/crates/ra_parser/src/grammar/params.rs
@@ -7,54 +7,59 @@ use super::*;
7// fn b(x: i32) {} 7// fn b(x: i32) {}
8// fn c(x: i32, ) {} 8// fn c(x: i32, ) {}
9// fn d(x: i32, y: ()) {} 9// fn d(x: i32, y: ()) {}
10pub(super) fn param_list(p: &mut Parser) { 10pub(super) fn param_list_fn(p: &mut Parser) {
11 list_(p, Flavor::Normal) 11 list_(p, Flavor::Function)
12} 12}
13 13
14// test param_list_opt_patterns 14// test param_list_opt_patterns
15// fn foo<F: FnMut(&mut Foo<'a>)>(){} 15// fn foo<F: FnMut(&mut Foo<'a>)>(){}
16pub(super) fn param_list_opt_patterns(p: &mut Parser) { 16pub(super) fn param_list_impl_fn(p: &mut Parser) {
17 list_(p, Flavor::OptionalPattern) 17 list_(p, Flavor::ImplFn)
18} 18}
19 19
20pub(super) fn param_list_opt_types(p: &mut Parser) { 20pub(super) fn param_list_fn_ptr(p: &mut Parser) {
21 list_(p, Flavor::OptionalType) 21 list_(p, Flavor::FnPointer)
22} 22}
23 23
24#[derive(Clone, Copy, Eq, PartialEq)] 24pub(super) fn param_list_closure(p: &mut Parser) {
25enum Flavor { 25 list_(p, Flavor::Closure)
26 OptionalType,
27 OptionalPattern,
28 Normal,
29} 26}
30 27
31impl Flavor { 28#[derive(Debug, Clone, Copy)]
32 fn type_required(self) -> bool { 29enum Flavor {
33 match self { 30 Function, // Includes trait fn params; omitted param idents are not supported
34 Flavor::OptionalType => false, 31 ImplFn,
35 _ => true, 32 FnPointer,
36 } 33 Closure
37 }
38} 34}
39 35
40fn list_(p: &mut Parser, flavor: Flavor) { 36fn list_(p: &mut Parser, flavor: Flavor) {
41 let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) }; 37 use Flavor::*;
42 assert!(p.at(bra)); 38
39 let (bra, ket) = match flavor {
40 Closure => (T![|], T![|]),
41 Function | ImplFn | FnPointer => (T!['('], T![')'])
42 };
43
43 let m = p.start(); 44 let m = p.start();
44 p.bump(bra); 45 p.bump(bra);
45 if flavor.type_required() { 46
47 if let Function = flavor {
46 // test self_param_outer_attr 48 // test self_param_outer_attr
47 // fn f(#[must_use] self) {} 49 // fn f(#[must_use] self) {}
48 attributes::outer_attributes(p); 50 attributes::outer_attributes(p);
49 opt_self_param(p); 51 opt_self_param(p);
50 } 52 }
53
51 while !p.at(EOF) && !p.at(ket) { 54 while !p.at(EOF) && !p.at(ket) {
52 // test param_outer_arg 55 // test param_outer_arg
53 // fn f(#[attr1] pat: Type) {} 56 // fn f(#[attr1] pat: Type) {}
54 attributes::outer_attributes(p); 57 attributes::outer_attributes(p);
55 58
56 if flavor.type_required() && p.at(T![...]) { 59 if let Function | FnPointer = flavor {
57 break; 60 if p.at(T![...]) {
61 break;
62 }
58 } 63 }
59 64
60 if !p.at_ts(VALUE_PARAMETER_FIRST) { 65 if !p.at_ts(VALUE_PARAMETER_FIRST) {
@@ -68,7 +73,7 @@ fn list_(p: &mut Parser, flavor: Flavor) {
68 } 73 }
69 // test param_list_vararg 74 // test param_list_vararg
70 // extern "C" { fn printf(format: *const i8, ...) -> i32; } 75 // extern "C" { fn printf(format: *const i8, ...) -> i32; }
71 if flavor.type_required() { 76 if let Function | FnPointer = flavor {
72 p.eat(T![...]); 77 p.eat(T![...]);
73 } 78 }
74 p.expect(ket); 79 p.expect(ket);
@@ -80,36 +85,52 @@ const VALUE_PARAMETER_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYP
80fn value_parameter(p: &mut Parser, flavor: Flavor) { 85fn value_parameter(p: &mut Parser, flavor: Flavor) {
81 let m = p.start(); 86 let m = p.start();
82 match flavor { 87 match flavor {
83 Flavor::OptionalType | Flavor::Normal => { 88 // test trait_fn_placeholder_parameter
89 // trait Foo {
90 // fn bar(_: u64, mut x: i32);
91 // }
92
93 // test trait_fn_patterns
94 // trait T {
95 // fn f1((a, b): (usize, usize)) {}
96 // fn f2(S { a, b }: S) {}
97 // fn f3(NewType(a): NewType) {}
98 // fn f4(&&a: &&usize) {}
99 // }
100
101 // test fn_patterns
102 // impl U {
103 // fn f1((a, b): (usize, usize)) {}
104 // fn f2(S { a, b }: S) {}
105 // fn f3(NewType(a): NewType) {}
106 // fn f4(&&a: &&usize) {}
107 // }
108 Flavor::Function => {
84 patterns::pattern(p); 109 patterns::pattern(p);
85 if p.at(T![:]) && !p.at(T![::]) || flavor.type_required() { 110 types::ascription(p);
86 types::ascription(p)
87 }
88 } 111 }
89 // test value_parameters_no_patterns 112 // test value_parameters_no_patterns
90 // type F = Box<Fn(a: i32, &b: &i32, &mut c: &i32, ())>; 113 // type F = Box<Fn(i32, &i32, &i32, ())>;
91 Flavor::OptionalPattern => { 114 Flavor::ImplFn => {
92 let la0 = p.current(); 115 types::type_(p);
93 let la1 = p.nth(1); 116 }
94 let la2 = p.nth(2); 117 // test fn_pointer_param_ident_path
95 let la3 = p.nth(3); 118 // type Foo = fn(Bar::Baz);
96 119 // type Qux = fn(baz: Bar::Baz);
97 // test trait_fn_placeholder_parameter 120 Flavor::FnPointer => {
98 // trait Foo { 121 if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
99 // fn bar(_: u64, mut x: i32);
100 // }
101 if (la0 == IDENT || la0 == T![_]) && la1 == T![:] && !p.nth_at(1, T![::])
102 || la0 == T![mut] && la1 == IDENT && la2 == T![:]
103 || la0 == T![&]
104 && (la1 == IDENT && la2 == T![:] && !p.nth_at(2, T![::])
105 || la1 == T![mut] && la2 == IDENT && la3 == T![:] && !p.nth_at(3, T![::]))
106 {
107 patterns::pattern(p); 122 patterns::pattern(p);
108 types::ascription(p); 123 types::ascription(p);
109 } else { 124 } else {
110 types::type_(p); 125 types::type_(p);
111 } 126 }
112 } 127 }
128 Flavor::Closure => {
129 patterns::pattern(p);
130 if p.at(T![:]) && !p.at(T![::]) {
131 types::ascription(p);
132 }
133 }
113 } 134 }
114 m.complete(p, PARAM); 135 m.complete(p, PARAM);
115} 136}
diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs
index ca8e075a1..186064320 100644
--- a/crates/ra_parser/src/grammar/paths.rs
+++ b/crates/ra_parser/src/grammar/paths.rs
@@ -97,9 +97,9 @@ fn opt_path_type_args(p: &mut Parser, mode: Mode) {
97 Mode::Use => return, 97 Mode::Use => return,
98 Mode::Type => { 98 Mode::Type => {
99 // test path_fn_trait_args 99 // test path_fn_trait_args
100 // type F = Box<Fn(x: i32) -> ()>; 100 // type F = Box<Fn(i32) -> ()>;
101 if p.at(T!['(']) { 101 if p.at(T!['(']) {
102 params::param_list_opt_patterns(p); 102 params::param_list_impl_fn(p);
103 opt_fn_ret_type(p); 103 opt_fn_ret_type(p);
104 } else { 104 } else {
105 type_args::opt_type_arg_list(p, false) 105 type_args::opt_type_arg_list(p, false)
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs
index 9b2e440fb..2c00bce80 100644
--- a/crates/ra_parser/src/grammar/types.rs
+++ b/crates/ra_parser/src/grammar/types.rs
@@ -183,7 +183,7 @@ fn fn_pointer_type(p: &mut Parser) {
183 return; 183 return;
184 } 184 }
185 if p.at(T!['(']) { 185 if p.at(T!['(']) {
186 params::param_list_opt_patterns(p); 186 params::param_list_fn_ptr(p);
187 } else { 187 } else {
188 p.error("expected parameters") 188 p.error("expected parameters")
189 } 189 }