aboutsummaryrefslogtreecommitdiff
path: root/crates/parser/src/grammar/items/use_item.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/parser/src/grammar/items/use_item.rs')
-rw-r--r--crates/parser/src/grammar/items/use_item.rs132
1 files changed, 132 insertions, 0 deletions
diff --git a/crates/parser/src/grammar/items/use_item.rs b/crates/parser/src/grammar/items/use_item.rs
new file mode 100644
index 000000000..20e6a13cf
--- /dev/null
+++ b/crates/parser/src/grammar/items/use_item.rs
@@ -0,0 +1,132 @@
1//! FIXME: write short doc here
2
3use super::*;
4
5pub(super) fn use_(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_rename(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}