parser/grammar/items/
use_item.rs

1use super::*;
2
3// test use_item
4// use std::collections;
5pub(super) fn use_(p: &mut Parser<'_>, m: Marker) {
6    p.bump(T![use]);
7    use_tree(p, true);
8    p.expect(T![;]);
9    m.complete(p, USE);
10}
11
12// test use_tree
13// use outer::tree::{inner::tree};
14fn use_tree(p: &mut Parser<'_>, top_level: bool) -> bool {
15    let m = p.start();
16    match p.current() {
17        // test use_tree_star
18        // use *;
19        // use std::{*};
20        T![*] => p.bump(T![*]),
21        // test use_tree_abs_star
22        // use ::*;
23        // use std::{::*};
24        T![:] if p.at(T![::]) && p.nth(2) == T![*] => {
25            p.bump(T![::]);
26            p.bump(T![*]);
27        }
28        T!['{'] => use_tree_list(p),
29        T![:] if p.at(T![::]) && p.nth(2) == T!['{'] => {
30            p.bump(T![::]);
31            use_tree_list(p);
32        }
33
34        // test use_tree_path
35        // use ::std;
36        // use std::collections;
37        //
38        // use self::m;
39        // use super::m;
40        // use crate::m;
41        _ if paths::is_use_path_start(p) => {
42            paths::use_path(p);
43            match p.current() {
44                // test use_tree_alias
45                // use std as stdlib;
46                // use Trait as _;
47                T![as] => opt_rename(p),
48                T![:] if p.at(T![::]) => {
49                    p.bump(T![::]);
50                    match p.current() {
51                        // test use_tree_path_star
52                        // use std::*;
53                        T![*] => p.bump(T![*]),
54                        // test use_tree_path_use_tree
55                        // use std::{collections};
56                        T!['{'] => use_tree_list(p),
57                        _ => p.error("expected `{` or `*`"),
58                    }
59                }
60                _ => (),
61            }
62        }
63        _ => {
64            m.abandon(p);
65            let msg = "expected one of `*`, `::`, `{`, `self`, `super` or an identifier";
66            if top_level {
67                p.err_recover(msg, ITEM_RECOVERY_SET);
68            } else {
69                // if we are parsing a nested tree, we have to eat a token to
70                // main balanced `{}`
71                p.err_and_bump(msg);
72            }
73            return false;
74        }
75    }
76    m.complete(p, USE_TREE);
77    true
78}
79
80pub(super) const USE_TREE_LIST_RECOVERY_SET: TokenSet =
81    TokenSet::new(&[T![;], T![,], T![.], T![ident]]).union(ITEM_RECOVERY_SET);
82
83pub(super) const USE_TREE_LIST_FIRST_SET: TokenSet = TokenSet::new(&[T!['{'], T![ident]]);
84
85// test use_tree_list
86// use {a, b, c};
87pub(crate) fn use_tree_list(p: &mut Parser<'_>) {
88    assert!(p.at(T!['{']));
89    let m = p.start();
90
91    // test_err use_tree_list_err_recovery
92    // use {a;
93    // use b;
94    // struct T;
95    // fn test() {}
96    // use {a ,, b};
97    delimited(
98        p,
99        T!['{'],
100        T!['}'],
101        T![,],
102        || "expected use tree".into(),
103        USE_TREE_LIST_FIRST_SET,
104        |p: &mut Parser<'_>| use_tree(p, false) || p.at_ts(USE_TREE_LIST_RECOVERY_SET),
105    );
106
107    m.complete(p, USE_TREE_LIST);
108}