aboutsummaryrefslogtreecommitdiff
path: root/src/parser/grammar
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-07-30 15:02:51 +0100
committerAleksey Kladov <[email protected]>2018-07-30 15:02:51 +0100
commitd4366940976a3d150a8b5bf92dc24f0162d4d62c (patch)
tree5d43e0d49dd2cdb322a3cd367655929dc3e3d3ef /src/parser/grammar
parent69c385e8105c7fad07a5728979e86a2a6a5e88ba (diff)
Path expressions
Diffstat (limited to 'src/parser/grammar')
-rw-r--r--src/parser/grammar/expressions.rs27
-rw-r--r--src/parser/grammar/mod.rs1
-rw-r--r--src/parser/grammar/paths.rs32
-rw-r--r--src/parser/grammar/type_args.rs26
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// }
7pub(super) fn literal(p: &mut Parser) -> bool { 16pub(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// }
57fn 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;
27mod paths; 27mod paths;
28mod patterns; 28mod patterns;
29mod type_params; 29mod type_params;
30mod type_args;
30mod types; 31mod types;
31 32
32use { 33use {
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
10pub(super) fn use_path(p: &mut Parser) { 10pub(super) fn use_path(p: &mut Parser) {
11 path(p) 11 path(p, Mode::Use)
12} 12}
13 13
14pub(super) fn type_path(p: &mut Parser) { 14pub(super) fn type_path(p: &mut Parser) {
15 path(p) 15 path(p, Mode::Type)
16} 16}
17 17
18fn path(p: &mut Parser) { 18pub(super) fn expr_path(p: &mut Parser) {
19 path(p, Mode::Expr)
20}
21
22#[derive(Clone, Copy, Eq, PartialEq)]
23enum Mode { Use, Type, Expr }
24
25fn 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
42fn path_segment(p: &mut Parser, first: bool) { 49fn 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
67fn 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 @@
1use super::*;
2
3pub(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}