aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar/items
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-08-12 16:06:49 +0100
committerAleksey Kladov <[email protected]>2020-08-12 16:14:23 +0100
commit50a02eb3593591a02677e1b56f24d7ff0459b9d0 (patch)
treea17351b1e3addea0a719f38990fea9289b6ef65e /crates/ra_parser/src/grammar/items
parent6dafc13f5f776980cd2560fb79d3d4790811c96d (diff)
Rename ra_parser -> parser
Diffstat (limited to 'crates/ra_parser/src/grammar/items')
-rw-r--r--crates/ra_parser/src/grammar/items/adt.rs178
-rw-r--r--crates/ra_parser/src/grammar/items/consts.rs33
-rw-r--r--crates/ra_parser/src/grammar/items/traits.rs153
-rw-r--r--crates/ra_parser/src/grammar/items/use_item.rs132
4 files changed, 0 insertions, 496 deletions
diff --git a/crates/ra_parser/src/grammar/items/adt.rs b/crates/ra_parser/src/grammar/items/adt.rs
deleted file mode 100644
index addfb59d4..000000000
--- a/crates/ra_parser/src/grammar/items/adt.rs
+++ /dev/null
@@ -1,178 +0,0 @@
1//! FIXME: write short doc here
2
3use super::*;
4
5pub(super) fn struct_def(p: &mut Parser, m: Marker) {
6 assert!(p.at(T![struct]));
7 p.bump(T![struct]);
8 struct_or_union(p, m, T![struct], STRUCT);
9}
10
11pub(super) fn union_def(p: &mut Parser, m: Marker) {
12 assert!(p.at_contextual_kw("union"));
13 p.bump_remap(T![union]);
14 struct_or_union(p, m, T![union], UNION);
15}
16
17fn struct_or_union(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
18 name_r(p, ITEM_RECOVERY_SET);
19 type_params::opt_type_param_list(p);
20 match p.current() {
21 T![where] => {
22 type_params::opt_where_clause(p);
23 match p.current() {
24 T![;] => {
25 p.bump(T![;]);
26 }
27 T!['{'] => record_field_def_list(p),
28 _ => {
29 //FIXME: special case `(` error message
30 p.error("expected `;` or `{`");
31 }
32 }
33 }
34 T![;] if kw == T![struct] => {
35 p.bump(T![;]);
36 }
37 T!['{'] => record_field_def_list(p),
38 T!['('] if kw == T![struct] => {
39 tuple_field_def_list(p);
40 // test tuple_struct_where
41 // struct Test<T>(T) where T: Clone;
42 // struct Test<T>(T);
43 type_params::opt_where_clause(p);
44 p.expect(T![;]);
45 }
46 _ if kw == T![struct] => {
47 p.error("expected `;`, `{`, or `(`");
48 }
49 _ => {
50 p.error("expected `{`");
51 }
52 }
53 m.complete(p, def);
54}
55
56pub(super) fn enum_def(p: &mut Parser, m: Marker) {
57 assert!(p.at(T![enum]));
58 p.bump(T![enum]);
59 name_r(p, ITEM_RECOVERY_SET);
60 type_params::opt_type_param_list(p);
61 type_params::opt_where_clause(p);
62 if p.at(T!['{']) {
63 enum_variant_list(p);
64 } else {
65 p.error("expected `{`")
66 }
67 m.complete(p, ENUM);
68}
69
70pub(crate) fn enum_variant_list(p: &mut Parser) {
71 assert!(p.at(T!['{']));
72 let m = p.start();
73 p.bump(T!['{']);
74 while !p.at(EOF) && !p.at(T!['}']) {
75 if p.at(T!['{']) {
76 error_block(p, "expected enum variant");
77 continue;
78 }
79 let var = p.start();
80 attributes::outer_attributes(p);
81 if p.at(IDENT) {
82 name(p);
83 match p.current() {
84 T!['{'] => record_field_def_list(p),
85 T!['('] => tuple_field_def_list(p),
86 _ => (),
87 }
88
89 // test variant_discriminant
90 // enum E { X(i32) = 10 }
91 if p.eat(T![=]) {
92 expressions::expr(p);
93 }
94 var.complete(p, VARIANT);
95 } else {
96 var.abandon(p);
97 p.err_and_bump("expected enum variant");
98 }
99 if !p.at(T!['}']) {
100 p.expect(T![,]);
101 }
102 }
103 p.expect(T!['}']);
104 m.complete(p, VARIANT_LIST);
105}
106
107pub(crate) fn record_field_def_list(p: &mut Parser) {
108 assert!(p.at(T!['{']));
109 let m = p.start();
110 p.bump(T!['{']);
111 while !p.at(T!['}']) && !p.at(EOF) {
112 if p.at(T!['{']) {
113 error_block(p, "expected field");
114 continue;
115 }
116 record_field_def(p);
117 if !p.at(T!['}']) {
118 p.expect(T![,]);
119 }
120 }
121 p.expect(T!['}']);
122 m.complete(p, RECORD_FIELD_LIST);
123
124 fn record_field_def(p: &mut Parser) {
125 let m = p.start();
126 // test record_field_attrs
127 // struct S {
128 // #[serde(with = "url_serde")]
129 // pub uri: Uri,
130 // }
131 attributes::outer_attributes(p);
132 opt_visibility(p);
133 if p.at(IDENT) {
134 name(p);
135 p.expect(T![:]);
136 types::type_(p);
137 m.complete(p, RECORD_FIELD);
138 } else {
139 m.abandon(p);
140 p.err_and_bump("expected field declaration");
141 }
142 }
143}
144
145fn tuple_field_def_list(p: &mut Parser) {
146 assert!(p.at(T!['(']));
147 let m = p.start();
148 if !p.expect(T!['(']) {
149 return;
150 }
151 while !p.at(T![')']) && !p.at(EOF) {
152 let m = p.start();
153 // test tuple_field_attrs
154 // struct S (
155 // #[serde(with = "url_serde")]
156 // pub Uri,
157 // );
158 //
159 // enum S {
160 // Uri(#[serde(with = "url_serde")] Uri),
161 // }
162 attributes::outer_attributes(p);
163 opt_visibility(p);
164 if !p.at_ts(types::TYPE_FIRST) {
165 p.error("expected a type");
166 m.complete(p, ERROR);
167 break;
168 }
169 types::type_(p);
170 m.complete(p, TUPLE_FIELD);
171
172 if !p.at(T![')']) {
173 p.expect(T![,]);
174 }
175 }
176 p.expect(T![')']);
177 m.complete(p, TUPLE_FIELD_LIST);
178}
diff --git a/crates/ra_parser/src/grammar/items/consts.rs b/crates/ra_parser/src/grammar/items/consts.rs
deleted file mode 100644
index 35ad766dc..000000000
--- a/crates/ra_parser/src/grammar/items/consts.rs
+++ /dev/null
@@ -1,33 +0,0 @@
1//! FIXME: write short doc here
2
3use super::*;
4
5pub(super) fn static_def(p: &mut Parser, m: Marker) {
6 const_or_static(p, m, T![static], STATIC)
7}
8
9pub(super) fn const_def(p: &mut Parser, m: Marker) {
10 const_or_static(p, m, T![const], CONST)
11}
12
13fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
14 assert!(p.at(kw));
15 p.bump(kw);
16 p.eat(T![mut]); // FIXME: validator to forbid const mut
17
18 // Allow `_` in place of an identifier in a `const`.
19 let is_const_underscore = kw == T![const] && p.eat(T![_]);
20 if !is_const_underscore {
21 name(p);
22 }
23
24 // test_err static_underscore
25 // static _: i32 = 5;
26
27 types::ascription(p);
28 if p.eat(T![=]) {
29 expressions::expr(p);
30 }
31 p.expect(T![;]);
32 m.complete(p, def);
33}
diff --git a/crates/ra_parser/src/grammar/items/traits.rs b/crates/ra_parser/src/grammar/items/traits.rs
deleted file mode 100644
index 751ce65f2..000000000
--- a/crates/ra_parser/src/grammar/items/traits.rs
+++ /dev/null
@@ -1,153 +0,0 @@
1//! FIXME: write short doc here
2
3use super::*;
4
5// test trait_item
6// trait T<U>: Hash + Clone where U: Copy {}
7// trait X<U: Debug + Display>: Hash + Clone where U: Copy {}
8pub(super) fn trait_def(p: &mut Parser) {
9 assert!(p.at(T![trait]));
10 p.bump(T![trait]);
11 name_r(p, ITEM_RECOVERY_SET);
12 type_params::opt_type_param_list(p);
13 // test trait_alias
14 // trait Z<U> = T<U>;
15 // trait Z<U> = T<U> where U: Copy;
16 // trait Z<U> = where Self: T<U>;
17 if p.eat(T![=]) {
18 type_params::bounds_without_colon(p);
19 type_params::opt_where_clause(p);
20 p.expect(T![;]);
21 return;
22 }
23 if p.at(T![:]) {
24 type_params::bounds(p);
25 }
26 type_params::opt_where_clause(p);
27 if p.at(T!['{']) {
28 trait_item_list(p);
29 } else {
30 p.error("expected `{`");
31 }
32}
33
34// test trait_item_list
35// impl F {
36// type A: Clone;
37// const B: i32;
38// fn foo() {}
39// fn bar(&self);
40// }
41pub(crate) fn trait_item_list(p: &mut Parser) {
42 assert!(p.at(T!['{']));
43 let m = p.start();
44 p.bump(T!['{']);
45 while !p.at(EOF) && !p.at(T!['}']) {
46 if p.at(T!['{']) {
47 error_block(p, "expected an item");
48 continue;
49 }
50 item_or_macro(p, true);
51 }
52 p.expect(T!['}']);
53 m.complete(p, ASSOC_ITEM_LIST);
54}
55
56// test impl_def
57// impl Foo {}
58pub(super) fn impl_def(p: &mut Parser) {
59 assert!(p.at(T![impl]));
60 p.bump(T![impl]);
61 if choose_type_params_over_qpath(p) {
62 type_params::opt_type_param_list(p);
63 }
64
65 // FIXME: never type
66 // impl ! {}
67
68 // test impl_def_neg
69 // impl !Send for X {}
70 p.eat(T![!]);
71 impl_type(p);
72 if p.eat(T![for]) {
73 impl_type(p);
74 }
75 type_params::opt_where_clause(p);
76 if p.at(T!['{']) {
77 impl_item_list(p);
78 } else {
79 p.error("expected `{`");
80 }
81}
82
83// test impl_item_list
84// impl F {
85// type A = i32;
86// const B: i32 = 92;
87// fn foo() {}
88// fn bar(&self) {}
89// }
90pub(crate) fn impl_item_list(p: &mut Parser) {
91 assert!(p.at(T!['{']));
92 let m = p.start();
93 p.bump(T!['{']);
94 // test impl_inner_attributes
95 // enum F{}
96 // impl F {
97 // //! This is a doc comment
98 // #![doc("This is also a doc comment")]
99 // }
100 attributes::inner_attributes(p);
101
102 while !p.at(EOF) && !p.at(T!['}']) {
103 if p.at(T!['{']) {
104 error_block(p, "expected an item");
105 continue;
106 }
107 item_or_macro(p, true);
108 }
109 p.expect(T!['}']);
110 m.complete(p, ASSOC_ITEM_LIST);
111}
112
113// test impl_type_params
114// impl<const N: u32> Bar<N> {}
115fn choose_type_params_over_qpath(p: &Parser) -> bool {
116 // There's an ambiguity between generic parameters and qualified paths in impls.
117 // If we see `<` it may start both, so we have to inspect some following tokens.
118 // The following combinations can only start generics,
119 // but not qualified paths (with one exception):
120 // `<` `>` - empty generic parameters
121 // `<` `#` - generic parameters with attributes
122 // `<` `const` - const generic parameters
123 // `<` (LIFETIME|IDENT) `>` - single generic parameter
124 // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
125 // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
126 // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
127 // The only truly ambiguous case is
128 // `<` IDENT `>` `::` IDENT ...
129 // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
130 // because this is what almost always expected in practice, qualified paths in impls
131 // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
132 if !p.at(T![<]) {
133 return false;
134 }
135 if p.nth(1) == T![#] || p.nth(1) == T![>] || p.nth(1) == CONST_KW {
136 return true;
137 }
138 (p.nth(1) == LIFETIME || p.nth(1) == IDENT)
139 && (p.nth(2) == T![>] || p.nth(2) == T![,] || p.nth(2) == T![:] || p.nth(2) == T![=])
140}
141
142// test_err impl_type
143// impl Type {}
144// impl Trait1 for T {}
145// impl impl NotType {}
146// impl Trait2 for impl NotType {}
147pub(crate) fn impl_type(p: &mut Parser) {
148 if p.at(T![impl]) {
149 p.error("expected trait or type");
150 return;
151 }
152 types::type_(p);
153}
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs
deleted file mode 100644
index 8e836a77e..000000000
--- a/crates/ra_parser/src/grammar/items/use_item.rs
+++ /dev/null
@@ -1,132 +0,0 @@
1//! FIXME: write short doc here
2
3use super::*;
4
5pub(super) fn use_item(p: &mut Parser, m: Marker) {
6 assert!(p.at(T![use]));
7 p.bump(T![use]);
8 use_tree(p, true);
9 p.expect(T![;]);
10 m.complete(p, USE);
11}
12
13/// Parse a use 'tree', such as `some::path` in `use some::path;`
14/// Note that this is called both by `use_item` and `use_tree_list`,
15/// so handles both `some::path::{inner::path}` and `inner::path` in
16/// `use some::path::{inner::path};`
17fn use_tree(p: &mut Parser, top_level: bool) {
18 let m = p.start();
19 match p.current() {
20 // Finish the use_tree for cases of e.g.
21 // `use some::path::{self, *};` or `use *;`
22 // This does not handle cases such as `use some::path::*`
23 // N.B. in Rust 2015 `use *;` imports all from crate root
24 // however in Rust 2018 `use *;` errors: ('cannot glob-import all possible crates')
25 // FIXME: Add this error (if not out of scope)
26
27 // test use_star
28 // use *;
29 // use ::*;
30 // use some::path::{*};
31 // use some::path::{::*};
32 T![*] => p.bump(T![*]),
33 T![:] if p.at(T![::]) && p.nth(2) == T![*] => {
34 // Parse `use ::*;`, which imports all from the crate root in Rust 2015
35 // This is invalid inside a use_tree_list, (e.g. `use some::path::{::*}`)
36 // but still parses and errors later: ('crate root in paths can only be used in start position')
37 // FIXME: Add this error (if not out of scope)
38 // In Rust 2018, it is always invalid (see above)
39 p.bump(T![::]);
40 p.bump(T![*]);
41 }
42 // Open a use tree list
43 // Handles cases such as `use {some::path};` or `{inner::path}` in
44 // `use some::path::{{inner::path}, other::path}`
45
46 // test use_tree_list
47 // use {crate::path::from::root, or::path::from::crate_name}; // Rust 2018 (with a crate named `or`)
48 // use {path::from::root}; // Rust 2015
49 // use ::{some::arbritrary::path}; // Rust 2015
50 // use ::{{{root::export}}}; // Nonsensical but perfectly legal nesting
51 T!['{'] => {
52 use_tree_list(p);
53 }
54 T![:] if p.at(T![::]) && p.nth(2) == T!['{'] => {
55 p.bump(T![::]);
56 use_tree_list(p);
57 }
58 // Parse a 'standard' path.
59 // Also handles aliases (e.g. `use something as something_else`)
60
61 // test use_path
62 // use ::crate_name; // Rust 2018 - All flavours
63 // use crate_name; // Rust 2018 - Anchored paths
64 // use item_in_scope_or_crate_name; // Rust 2018 - Uniform Paths
65 //
66 // use self::module::Item;
67 // use crate::Item;
68 // use self::some::Struct;
69 // use crate_name::some_item;
70 _ if paths::is_use_path_start(p) => {
71 paths::use_path(p);
72 match p.current() {
73 T![as] => {
74 // test use_alias
75 // use some::path as some_name;
76 // use some::{
77 // other::path as some_other_name,
78 // different::path as different_name,
79 // yet::another::path,
80 // running::out::of::synonyms::for_::different::*
81 // };
82 // use Trait as _;
83 opt_alias(p);
84 }
85 T![:] if p.at(T![::]) => {
86 p.bump(T![::]);
87 match p.current() {
88 T![*] => {
89 p.bump(T![*]);
90 }
91 // test use_tree_list_after_path
92 // use crate::{Item};
93 // use self::{Item};
94 T!['{'] => use_tree_list(p),
95 _ => {
96 // is this unreachable?
97 p.error("expected `{` or `*`");
98 }
99 }
100 }
101 _ => (),
102 }
103 }
104 _ => {
105 m.abandon(p);
106 let msg = "expected one of `*`, `::`, `{`, `self`, `super` or an identifier";
107 if top_level {
108 p.err_recover(msg, ITEM_RECOVERY_SET);
109 } else {
110 // if we are parsing a nested tree, we have to eat a token to
111 // main balanced `{}`
112 p.err_and_bump(msg);
113 }
114 return;
115 }
116 }
117 m.complete(p, USE_TREE);
118}
119
120pub(crate) fn use_tree_list(p: &mut Parser) {
121 assert!(p.at(T!['{']));
122 let m = p.start();
123 p.bump(T!['{']);
124 while !p.at(EOF) && !p.at(T!['}']) {
125 use_tree(p, false);
126 if !p.at(T!['}']) {
127 p.expect(T![,]);
128 }
129 }
130 p.expect(T!['}']);
131 m.complete(p, USE_TREE_LIST);
132}