diff options
Diffstat (limited to 'src/grammar/paths.rs')
-rw-r--r-- | src/grammar/paths.rs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/grammar/paths.rs b/src/grammar/paths.rs new file mode 100644 index 000000000..fe69db096 --- /dev/null +++ b/src/grammar/paths.rs | |||
@@ -0,0 +1,77 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) fn is_path_start(p: &Parser) -> bool { | ||
4 | match p.current() { | ||
5 | IDENT | SELF_KW | SUPER_KW | COLONCOLON => true, | ||
6 | _ => false, | ||
7 | } | ||
8 | } | ||
9 | |||
10 | pub(super) fn use_path(p: &mut Parser) { | ||
11 | path(p, Mode::Use) | ||
12 | } | ||
13 | |||
14 | pub(super) fn type_path(p: &mut Parser) { | ||
15 | path(p, Mode::Type) | ||
16 | } | ||
17 | |||
18 | pub(super) fn expr_path(p: &mut Parser) { | ||
19 | path(p, Mode::Expr) | ||
20 | } | ||
21 | |||
22 | #[derive(Clone, Copy, Eq, PartialEq)] | ||
23 | enum Mode { | ||
24 | Use, | ||
25 | Type, | ||
26 | Expr, | ||
27 | } | ||
28 | |||
29 | fn path(p: &mut Parser, mode: Mode) { | ||
30 | if !is_path_start(p) { | ||
31 | return; | ||
32 | } | ||
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 | |||
53 | fn path_segment(p: &mut Parser, mode: Mode, first: bool) { | ||
54 | let segment = p.start(); | ||
55 | if first { | ||
56 | p.eat(COLONCOLON); | ||
57 | } | ||
58 | match p.current() { | ||
59 | IDENT => { | ||
60 | name_ref(p); | ||
61 | path_generic_args(p, mode); | ||
62 | } | ||
63 | SELF_KW | SUPER_KW => p.bump(), | ||
64 | _ => { | ||
65 | p.error("expected identifier"); | ||
66 | } | ||
67 | }; | ||
68 | segment.complete(p, PATH_SEGMENT); | ||
69 | } | ||
70 | |||
71 | fn path_generic_args(p: &mut Parser, mode: Mode) { | ||
72 | match mode { | ||
73 | Mode::Use => return, | ||
74 | Mode::Type => type_args::type_arg_list(p, false), | ||
75 | Mode::Expr => type_args::type_arg_list(p, true), | ||
76 | } | ||
77 | } | ||