aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r--crates/ra_syntax/src/grammar/mod.rs5
-rw-r--r--crates/ra_syntax/src/grammar/type_params.rs86
-rw-r--r--crates/ra_syntax/src/grammar/types.rs13
-rw-r--r--crates/ra_syntax/src/lib.rs3
4 files changed, 70 insertions, 37 deletions
diff --git a/crates/ra_syntax/src/grammar/mod.rs b/crates/ra_syntax/src/grammar/mod.rs
index c87564073..95c437983 100644
--- a/crates/ra_syntax/src/grammar/mod.rs
+++ b/crates/ra_syntax/src/grammar/mod.rs
@@ -21,6 +21,11 @@
21//! After adding a new inline-test, run `cargo collect-tests` to extract 21//! After adding a new inline-test, run `cargo collect-tests` to extract
22//! it as a standalone text-fixture into `tests/data/parser/inline`, and 22//! it as a standalone text-fixture into `tests/data/parser/inline`, and
23//! run `cargo test` once to create the "gold" value. 23//! run `cargo test` once to create the "gold" value.
24//!
25//! Coding convention: rules like `where_clause` always produce either a
26//! node or an error, rules like `opt_where_clause` may produce nothing.
27//! Non-opt rules typically start with `assert!(p.at(FIRST_TOKEN))`, the
28//! caller is responsible for branching on the first token.
24mod attributes; 29mod attributes;
25mod expressions; 30mod expressions;
26mod items; 31mod items;
diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs
index 79f5036b4..68eca0ce8 100644
--- a/crates/ra_syntax/src/grammar/type_params.rs
+++ b/crates/ra_syntax/src/grammar/type_params.rs
@@ -4,6 +4,11 @@ pub(super) fn opt_type_param_list(p: &mut Parser) {
4 if !p.at(L_ANGLE) { 4 if !p.at(L_ANGLE) {
5 return; 5 return;
6 } 6 }
7 type_param_list(p);
8}
9
10fn type_param_list(p: &mut Parser) {
11 assert!(p.at(L_ANGLE));
7 let m = p.start(); 12 let m = p.start();
8 p.bump(); 13 p.bump();
9 14
@@ -19,32 +24,32 @@ pub(super) fn opt_type_param_list(p: &mut Parser) {
19 } 24 }
20 p.expect(R_ANGLE); 25 p.expect(R_ANGLE);
21 m.complete(p, TYPE_PARAM_LIST); 26 m.complete(p, TYPE_PARAM_LIST);
27}
22 28
23 fn lifetime_param(p: &mut Parser) { 29fn lifetime_param(p: &mut Parser) {
24 assert!(p.at(LIFETIME)); 30 assert!(p.at(LIFETIME));
25 let m = p.start(); 31 let m = p.start();
26 p.bump(); 32 p.bump();
27 if p.at(COLON) { 33 if p.at(COLON) {
28 lifetime_bounds(p); 34 lifetime_bounds(p);
29 }
30 m.complete(p, LIFETIME_PARAM);
31 } 35 }
36 m.complete(p, LIFETIME_PARAM);
37}
32 38
33 fn type_param(p: &mut Parser) { 39fn type_param(p: &mut Parser) {
34 assert!(p.at(IDENT)); 40 assert!(p.at(IDENT));
35 let m = p.start(); 41 let m = p.start();
36 name(p); 42 name(p);
37 if p.at(COLON) { 43 if p.at(COLON) {
38 bounds(p); 44 bounds(p);
39 }
40 // test type_param_default
41 // struct S<T = i32>;
42 if p.at(EQ) {
43 p.bump();
44 types::type_(p)
45 }
46 m.complete(p, TYPE_PARAM);
47 } 45 }
46 // test type_param_default
47 // struct S<T = i32>;
48 if p.at(EQ) {
49 p.bump();
50 types::type_(p)
51 }
52 m.complete(p, TYPE_PARAM);
48} 53}
49 54
50// test type_param_bounds 55// test type_param_bounds
@@ -99,7 +104,7 @@ pub(super) fn opt_where_clause(p: &mut Parser) {
99 let m = p.start(); 104 let m = p.start();
100 p.bump(); 105 p.bump();
101 loop { 106 loop {
102 if !(paths::is_path_start(p) || p.current() == LIFETIME) { 107 if !(paths::is_path_start(p) || p.current() == LIFETIME || p.current() == FOR_KW) {
103 break; 108 break;
104 } 109 }
105 where_predicate(p); 110 where_predicate(p);
@@ -112,19 +117,30 @@ pub(super) fn opt_where_clause(p: &mut Parser) {
112 117
113fn where_predicate(p: &mut Parser) { 118fn where_predicate(p: &mut Parser) {
114 let m = p.start(); 119 let m = p.start();
115 if p.at(LIFETIME) { 120 match p.current() {
116 p.eat(LIFETIME); 121 LIFETIME => {
117 if p.at(COLON) { 122 p.bump();
118 lifetime_bounds(p) 123 if p.at(COLON) {
119 } else { 124 lifetime_bounds(p);
120 p.error("expected colon") 125 } else {
126 p.error("expected colon");
127 }
121 } 128 }
122 } else { 129 _ => {
123 types::path_type(p); 130 // test where_pred_for
124 if p.at(COLON) { 131 // fn test<F>()
125 bounds(p); 132 // where
126 } else { 133 // for<'a> F: Fn(&'a str)
127 p.error("expected colon") 134 // { }
135 if p.at(FOR_KW) {
136 types::for_binder(p);
137 }
138 types::path_type(p);
139 if p.at(COLON) {
140 bounds(p);
141 } else {
142 p.error("expected colon");
143 }
128 } 144 }
129 } 145 }
130 m.complete(p, WHERE_PRED); 146 m.complete(p, WHERE_PRED);
diff --git a/crates/ra_syntax/src/grammar/types.rs b/crates/ra_syntax/src/grammar/types.rs
index f308aef89..ed2718e73 100644
--- a/crates/ra_syntax/src/grammar/types.rs
+++ b/crates/ra_syntax/src/grammar/types.rs
@@ -188,13 +188,22 @@ fn fn_pointer_type(p: &mut Parser) {
188 m.complete(p, FN_POINTER_TYPE); 188 m.complete(p, FN_POINTER_TYPE);
189} 189}
190 190
191pub(super) fn for_binder(p: &mut Parser) {
192 assert!(p.at(FOR_KW));
193 p.bump();
194 if p.at(L_ANGLE) {
195 type_params::opt_type_param_list(p);
196 } else {
197 p.error("expected `<`");
198 }
199}
200
191// test for_type 201// test for_type
192// type A = for<'a> fn() -> (); 202// type A = for<'a> fn() -> ();
193pub(super) fn for_type(p: &mut Parser) { 203pub(super) fn for_type(p: &mut Parser) {
194 assert!(p.at(FOR_KW)); 204 assert!(p.at(FOR_KW));
195 let m = p.start(); 205 let m = p.start();
196 p.bump(); 206 for_binder(p);
197 type_params::opt_type_param_list(p);
198 match p.current() { 207 match p.current() {
199 FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p), 208 FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p),
200 _ if paths::is_path_start(p) => path_type_(p, false), 209 _ if paths::is_path_start(p) => path_type_(p, false),
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 69a679d04..123002825 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -60,6 +60,7 @@ pub use crate::{
60 60
61use crate::yellow::GreenNode; 61use crate::yellow::GreenNode;
62 62
63/// File represents a parse tree for a single Rust file.
63#[derive(Clone, Debug, Hash, PartialEq, Eq)] 64#[derive(Clone, Debug, Hash, PartialEq, Eq)]
64pub struct File { 65pub struct File {
65 root: SyntaxNode, 66 root: SyntaxNode,
@@ -92,9 +93,11 @@ impl File {
92 text_utils::replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert); 93 text_utils::replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert);
93 File::parse(&text) 94 File::parse(&text)
94 } 95 }
96 /// Typed AST representation of the parse tree.
95 pub fn ast(&self) -> ast::Root { 97 pub fn ast(&self) -> ast::Root {
96 ast::Root::cast(self.syntax()).unwrap() 98 ast::Root::cast(self.syntax()).unwrap()
97 } 99 }
100 /// Untyped homogeneous representation of the parse tree.
98 pub fn syntax(&self) -> SyntaxNodeRef { 101 pub fn syntax(&self) -> SyntaxNodeRef {
99 self.root.borrowed() 102 self.root.borrowed()
100 } 103 }