diff options
author | Aleksey Kladov <[email protected]> | 2018-07-30 15:02:51 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-07-30 15:02:51 +0100 |
commit | d4366940976a3d150a8b5bf92dc24f0162d4d62c (patch) | |
tree | 5d43e0d49dd2cdb322a3cd367655929dc3e3d3ef /src/parser | |
parent | 69c385e8105c7fad07a5728979e86a2a6a5e88ba (diff) |
Path expressions
Diffstat (limited to 'src/parser')
-rw-r--r-- | src/parser/grammar/expressions.rs | 27 | ||||
-rw-r--r-- | src/parser/grammar/mod.rs | 1 | ||||
-rw-r--r-- | src/parser/grammar/paths.rs | 32 | ||||
-rw-r--r-- | src/parser/grammar/type_args.rs | 26 |
4 files changed, 78 insertions, 8 deletions
diff --git a/src/parser/grammar/expressions.rs b/src/parser/grammar/expressions.rs index 40f41535e..ece698248 100644 --- a/src/parser/grammar/expressions.rs +++ b/src/parser/grammar/expressions.rs | |||
@@ -2,7 +2,16 @@ use super::*; | |||
2 | 2 | ||
3 | // test expr_literals | 3 | // test expr_literals |
4 | // fn foo() { | 4 | // fn foo() { |
5 | // let _ = 92; | 5 | // let _ = true; |
6 | // let _ = false; | ||
7 | // let _ = 1; | ||
8 | // let _ = 2.0; | ||
9 | // let _ = b'a'; | ||
10 | // let _ = 'b'; | ||
11 | // let _ = "c"; | ||
12 | // let _ = r"d"; | ||
13 | // let _ = b"e"; | ||
14 | // let _ = br"f"; | ||
6 | // } | 15 | // } |
7 | pub(super) fn literal(p: &mut Parser) -> bool { | 16 | pub(super) fn literal(p: &mut Parser) -> bool { |
8 | match p.current() { | 17 | match p.current() { |
@@ -21,6 +30,9 @@ pub(super) fn expr(p: &mut Parser) { | |||
21 | if literal(p) { | 30 | if literal(p) { |
22 | return; | 31 | return; |
23 | } | 32 | } |
33 | if paths::is_path_start(p) { | ||
34 | return path_expr(p); | ||
35 | } | ||
24 | 36 | ||
25 | match p.current() { | 37 | match p.current() { |
26 | L_PAREN => tuple_expr(p), | 38 | L_PAREN => tuple_expr(p), |
@@ -35,3 +47,16 @@ fn tuple_expr(p: &mut Parser) { | |||
35 | p.expect(R_PAREN); | 47 | p.expect(R_PAREN); |
36 | m.complete(p, TUPLE_EXPR); | 48 | m.complete(p, TUPLE_EXPR); |
37 | } | 49 | } |
50 | |||
51 | // test path_expr | ||
52 | // fn foo() { | ||
53 | // let _ = a; | ||
54 | // let _ = a::b; | ||
55 | // let _ = ::a::<b>; | ||
56 | // } | ||
57 | fn path_expr(p: &mut Parser) { | ||
58 | assert!(paths::is_path_start(p)); | ||
59 | let m = p.start(); | ||
60 | paths::expr_path(p); | ||
61 | m.complete(p, PATH_EXPR); | ||
62 | } | ||
diff --git a/src/parser/grammar/mod.rs b/src/parser/grammar/mod.rs index e24f1055e..e4823eadb 100644 --- a/src/parser/grammar/mod.rs +++ b/src/parser/grammar/mod.rs | |||
@@ -27,6 +27,7 @@ mod items; | |||
27 | mod paths; | 27 | mod paths; |
28 | mod patterns; | 28 | mod patterns; |
29 | mod type_params; | 29 | mod type_params; |
30 | mod type_args; | ||
30 | mod types; | 31 | mod types; |
31 | 32 | ||
32 | use { | 33 | use { |
diff --git a/src/parser/grammar/paths.rs b/src/parser/grammar/paths.rs index d3eb20ea1..69ed84665 100644 --- a/src/parser/grammar/paths.rs +++ b/src/parser/grammar/paths.rs | |||
@@ -8,19 +8,26 @@ pub(super) fn is_path_start(p: &Parser) -> bool { | |||
8 | } | 8 | } |
9 | 9 | ||
10 | pub(super) fn use_path(p: &mut Parser) { | 10 | pub(super) fn use_path(p: &mut Parser) { |
11 | path(p) | 11 | path(p, Mode::Use) |
12 | } | 12 | } |
13 | 13 | ||
14 | pub(super) fn type_path(p: &mut Parser) { | 14 | pub(super) fn type_path(p: &mut Parser) { |
15 | path(p) | 15 | path(p, Mode::Type) |
16 | } | 16 | } |
17 | 17 | ||
18 | fn path(p: &mut Parser) { | 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 { Use, Type, Expr } | ||
24 | |||
25 | fn path(p: &mut Parser, mode: Mode) { | ||
19 | if !is_path_start(p) { | 26 | if !is_path_start(p) { |
20 | return; | 27 | return; |
21 | } | 28 | } |
22 | let path = p.start(); | 29 | let path = p.start(); |
23 | path_segment(p, true); | 30 | path_segment(p, mode, true); |
24 | let mut qual = path.complete(p, PATH); | 31 | let mut qual = path.complete(p, PATH); |
25 | loop { | 32 | loop { |
26 | let use_tree = match p.nth(1) { | 33 | let use_tree = match p.nth(1) { |
@@ -30,7 +37,7 @@ fn path(p: &mut Parser) { | |||
30 | if p.at(COLONCOLON) && !use_tree { | 37 | if p.at(COLONCOLON) && !use_tree { |
31 | let path = qual.precede(p); | 38 | let path = qual.precede(p); |
32 | p.bump(); | 39 | p.bump(); |
33 | path_segment(p, false); | 40 | path_segment(p, mode, false); |
34 | let path = path.complete(p, PATH); | 41 | let path = path.complete(p, PATH); |
35 | qual = path; | 42 | qual = path; |
36 | } else { | 43 | } else { |
@@ -39,13 +46,16 @@ fn path(p: &mut Parser) { | |||
39 | } | 46 | } |
40 | } | 47 | } |
41 | 48 | ||
42 | fn path_segment(p: &mut Parser, first: bool) { | 49 | fn path_segment(p: &mut Parser, mode: Mode, first: bool) { |
43 | let segment = p.start(); | 50 | let segment = p.start(); |
44 | if first { | 51 | if first { |
45 | p.eat(COLONCOLON); | 52 | p.eat(COLONCOLON); |
46 | } | 53 | } |
47 | match p.current() { | 54 | match p.current() { |
48 | IDENT => name_ref(p), | 55 | IDENT => { |
56 | name_ref(p); | ||
57 | path_generic_args(p, mode); | ||
58 | }, | ||
49 | SELF_KW | SUPER_KW => p.bump(), | 59 | SELF_KW | SUPER_KW => p.bump(), |
50 | _ => { | 60 | _ => { |
51 | p.error("expected identifier"); | 61 | p.error("expected identifier"); |
@@ -53,3 +63,11 @@ fn path_segment(p: &mut Parser, first: bool) { | |||
53 | }; | 63 | }; |
54 | segment.complete(p, PATH_SEGMENT); | 64 | segment.complete(p, PATH_SEGMENT); |
55 | } | 65 | } |
66 | |||
67 | fn path_generic_args(p: &mut Parser, mode: Mode) { | ||
68 | match mode { | ||
69 | Mode::Use => return, | ||
70 | Mode::Type => type_args::list(p, false), | ||
71 | Mode::Expr => type_args::list(p, true), | ||
72 | } | ||
73 | } | ||
diff --git a/src/parser/grammar/type_args.rs b/src/parser/grammar/type_args.rs new file mode 100644 index 000000000..20e75b4b0 --- /dev/null +++ b/src/parser/grammar/type_args.rs | |||
@@ -0,0 +1,26 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) fn list(p: &mut Parser, colon_colon_required: bool) { | ||
4 | let m; | ||
5 | match (colon_colon_required, p.nth(0), p.nth(1)) { | ||
6 | (_, COLONCOLON, L_ANGLE) => { | ||
7 | m = p.start(); | ||
8 | p.bump(); | ||
9 | p.bump(); | ||
10 | } | ||
11 | (false, L_ANGLE, _) => { | ||
12 | m = p.start(); | ||
13 | p.bump(); | ||
14 | } | ||
15 | _ => return | ||
16 | }; | ||
17 | |||
18 | while !p.at(EOF) && !p.at(R_ANGLE) { | ||
19 | types::type_(p); | ||
20 | if !p.at(R_ANGLE) && !p.expect(COMMA) { | ||
21 | break; | ||
22 | } | ||
23 | } | ||
24 | p.expect(R_ANGLE); | ||
25 | m.complete(p, TYPE_ARG_LIST); | ||
26 | } | ||