diff options
Diffstat (limited to 'src/parser/grammar/paths.rs')
-rw-r--r-- | src/parser/grammar/paths.rs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/parser/grammar/paths.rs b/src/parser/grammar/paths.rs new file mode 100644 index 000000000..6efac2610 --- /dev/null +++ b/src/parser/grammar/paths.rs | |||
@@ -0,0 +1,49 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) fn is_path_start(p: &Parser) -> bool { | ||
4 | AnyOf(&[IDENT, SELF_KW, SUPER_KW, COLONCOLON]).is_ahead(p) | ||
5 | } | ||
6 | |||
7 | pub(super) fn use_path(p: &mut Parser) { | ||
8 | path(p) | ||
9 | } | ||
10 | |||
11 | pub(super) fn type_path(p: &mut Parser) { | ||
12 | path(p) | ||
13 | } | ||
14 | |||
15 | fn path(p: &mut Parser) { | ||
16 | if !is_path_start(p) { | ||
17 | return; | ||
18 | } | ||
19 | let path = p.start(); | ||
20 | path_segment(p, true); | ||
21 | let mut qual = path.complete(p, PATH); | ||
22 | loop { | ||
23 | let use_tree = match p.nth(1) { | ||
24 | STAR | L_CURLY => true, | ||
25 | _ => false, | ||
26 | }; | ||
27 | if p.at(COLONCOLON) && !use_tree { | ||
28 | let path = qual.precede(p); | ||
29 | p.bump(); | ||
30 | path_segment(p, false); | ||
31 | let path = path.complete(p, PATH); | ||
32 | qual = path; | ||
33 | } else { | ||
34 | break; | ||
35 | } | ||
36 | } | ||
37 | } | ||
38 | |||
39 | fn path_segment(p: &mut Parser, first: bool) { | ||
40 | let segment = p.start(); | ||
41 | if first { | ||
42 | p.eat(COLONCOLON); | ||
43 | } | ||
44 | match p.current() { | ||
45 | IDENT | SELF_KW | SUPER_KW => p.bump(), | ||
46 | _ => p.error().message("expected identifier").emit(), | ||
47 | }; | ||
48 | segment.complete(p, PATH_SEGMENT); | ||
49 | } | ||