aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar/paths.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/grammar/paths.rs')
-rw-r--r--crates/ra_parser/src/grammar/paths.rs103
1 files changed, 103 insertions, 0 deletions
diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs
new file mode 100644
index 000000000..33a11886c
--- /dev/null
+++ b/crates/ra_parser/src/grammar/paths.rs
@@ -0,0 +1,103 @@
1use super::*;
2
3pub(super) const PATH_FIRST: TokenSet =
4 token_set![IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLONCOLON, L_ANGLE];
5
6pub(super) fn is_path_start(p: &Parser) -> bool {
7 match p.current() {
8 IDENT | SELF_KW | SUPER_KW | CRATE_KW | COLONCOLON => true,
9 _ => false,
10 }
11}
12
13pub(super) fn use_path(p: &mut Parser) {
14 path(p, Mode::Use)
15}
16
17pub(super) fn type_path(p: &mut Parser) {
18 path(p, Mode::Type)
19}
20
21pub(super) fn expr_path(p: &mut Parser) {
22 path(p, Mode::Expr)
23}
24
25#[derive(Clone, Copy, Eq, PartialEq)]
26enum Mode {
27 Use,
28 Type,
29 Expr,
30}
31
32fn path(p: &mut Parser, mode: Mode) {
33 let path = p.start();
34 path_segment(p, mode, true);
35 let mut qual = path.complete(p, PATH);
36 loop {
37 let use_tree = match p.nth(1) {
38 STAR | L_CURLY => true,
39 _ => false,
40 };
41 if p.at(COLONCOLON) && !use_tree {
42 let path = qual.precede(p);
43 p.bump();
44 path_segment(p, mode, false);
45 let path = path.complete(p, PATH);
46 qual = path;
47 } else {
48 break;
49 }
50 }
51}
52
53fn path_segment(p: &mut Parser, mode: Mode, first: bool) {
54 let m = p.start();
55 // test qual_paths
56 // type X = <A as B>::Output;
57 // fn foo() { <usize as Default>::default(); }
58 if first && p.eat(L_ANGLE) {
59 types::type_(p);
60 if p.eat(AS_KW) {
61 if is_path_start(p) {
62 types::path_type(p);
63 } else {
64 p.error("expected a trait");
65 }
66 }
67 p.expect(R_ANGLE);
68 } else {
69 if first {
70 p.eat(COLONCOLON);
71 }
72 match p.current() {
73 IDENT => {
74 name_ref(p);
75 opt_path_type_args(p, mode);
76 }
77 // test crate_path
78 // use crate::foo;
79 SELF_KW | SUPER_KW | CRATE_KW => p.bump(),
80 _ => {
81 p.err_recover("expected identifier", items::ITEM_RECOVERY_SET);
82 }
83 };
84 }
85 m.complete(p, PATH_SEGMENT);
86}
87
88fn opt_path_type_args(p: &mut Parser, mode: Mode) {
89 match mode {
90 Mode::Use => return,
91 Mode::Type => {
92 // test path_fn_trait_args
93 // type F = Box<Fn(x: i32) -> ()>;
94 if p.at(L_PAREN) {
95 params::param_list_opt_patterns(p);
96 opt_fn_ret_type(p);
97 } else {
98 type_args::opt_type_arg_list(p, false)
99 }
100 }
101 Mode::Expr => type_args::opt_type_arg_list(p, true),
102 }
103}