diff options
Diffstat (limited to 'crates/ra_parser/src')
-rw-r--r-- | crates/ra_parser/src/grammar.rs | 12 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 6 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/items.rs | 20 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/paths.rs | 15 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/patterns.rs | 8 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/type_params.rs | 11 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/types.rs | 16 | ||||
-rw-r--r-- | crates/ra_parser/src/parser.rs | 15 | ||||
-rw-r--r-- | crates/ra_parser/src/syntax_kind.rs | 5 |
9 files changed, 68 insertions, 40 deletions
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index be0cd5661..caedeead0 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -18,9 +18,10 @@ | |||
18 | //! // fn foo() {} | 18 | //! // fn foo() {} |
19 | //! ``` | 19 | //! ``` |
20 | //! | 20 | //! |
21 | //! After adding a new inline-test, run `cargo collect-tests` to extract | 21 | //! After adding a new inline-test, run `cargo xtask codegen` to |
22 | //! it as a standalone text-fixture into `tests/data/parser/inline`, and | 22 | //! extract it as a standalone text-fixture into |
23 | //! run `cargo test` once to create the "gold" value. | 23 | //! `crates/ra_syntax/test_data/parser/`, and run `cargo test` once to |
24 | //! create the "gold" value. | ||
24 | //! | 25 | //! |
25 | //! Coding convention: rules like `where_clause` always produce either a | 26 | //! Coding convention: rules like `where_clause` always produce either a |
26 | //! node or an error, rules like `opt_where_clause` may produce nothing. | 27 | //! node or an error, rules like `opt_where_clause` may produce nothing. |
@@ -72,10 +73,7 @@ pub(crate) mod fragments { | |||
72 | // Parse a meta item , which excluded [], e.g : #[ MetaItem ] | 73 | // Parse a meta item , which excluded [], e.g : #[ MetaItem ] |
73 | pub(crate) fn meta_item(p: &mut Parser) { | 74 | pub(crate) fn meta_item(p: &mut Parser) { |
74 | fn is_delimiter(p: &mut Parser) -> bool { | 75 | fn is_delimiter(p: &mut Parser) -> bool { |
75 | match p.current() { | 76 | matches!(p.current(), T!['{'] | T!['('] | T!['[']) |
76 | T!['{'] | T!['('] | T!['['] => true, | ||
77 | _ => false, | ||
78 | } | ||
79 | } | 77 | } |
80 | 78 | ||
81 | if is_delimiter(p) { | 79 | if is_delimiter(p) { |
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index d6e8df32a..6e72eea66 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -50,10 +50,8 @@ fn expr_no_struct(p: &mut Parser) { | |||
50 | } | 50 | } |
51 | 51 | ||
52 | fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool { | 52 | fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool { |
53 | match kind { | 53 | let forbid = matches!(kind, BIN_EXPR | RANGE_EXPR); |
54 | BIN_EXPR | RANGE_EXPR | IF_EXPR => false, | 54 | !forbid |
55 | _ => true, | ||
56 | } | ||
57 | } | 55 | } |
58 | 56 | ||
59 | pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { | 57 | pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) { |
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 67a924de5..97642bc24 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs | |||
@@ -118,7 +118,22 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul | |||
118 | && p.at_contextual_kw("default") | 118 | && p.at_contextual_kw("default") |
119 | && (match p.nth(1) { | 119 | && (match p.nth(1) { |
120 | T![impl] => true, | 120 | T![impl] => true, |
121 | T![fn] | T![type] => { | 121 | T![unsafe] => { |
122 | // test default_unsafe_impl | ||
123 | // default unsafe impl Foo {} | ||
124 | |||
125 | // test default_unsafe_fn | ||
126 | // impl T for Foo { | ||
127 | // default unsafe fn foo() {} | ||
128 | // } | ||
129 | if p.nth(2) == T![impl] || p.nth(2) == T![fn] { | ||
130 | p.bump_remap(T![default]); | ||
131 | p.bump(T![unsafe]); | ||
132 | has_mods = true; | ||
133 | } | ||
134 | false | ||
135 | } | ||
136 | T![fn] | T![type] | T![const] => { | ||
122 | if let ItemFlavor::Mod = flavor { | 137 | if let ItemFlavor::Mod = flavor { |
123 | true | 138 | true |
124 | } else { | 139 | } else { |
@@ -198,6 +213,9 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul | |||
198 | // default type T = Bar; | 213 | // default type T = Bar; |
199 | // default fn foo() {} | 214 | // default fn foo() {} |
200 | // } | 215 | // } |
216 | T![const] => { | ||
217 | consts::const_def(p, m); | ||
218 | } | ||
201 | 219 | ||
202 | // test unsafe_default_impl | 220 | // test unsafe_default_impl |
203 | // unsafe default impl Foo {} | 221 | // unsafe default impl Foo {} |
diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs index 332acc1a0..b503af1dc 100644 --- a/crates/ra_parser/src/grammar/paths.rs +++ b/crates/ra_parser/src/grammar/paths.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use super::*; | 3 | use super::*; |
4 | 4 | ||
5 | pub(super) const PATH_FIRST: TokenSet = | 5 | pub(super) const PATH_FIRST: TokenSet = |
6 | token_set![IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLON, L_ANGLE]; | 6 | token_set![IDENT, T![self], T![super], T![crate], T![:], T![<]]; |
7 | 7 | ||
8 | pub(super) fn is_path_start(p: &Parser) -> bool { | 8 | pub(super) fn is_path_start(p: &Parser) -> bool { |
9 | is_use_path_start(p) || p.at(T![<]) | 9 | is_use_path_start(p) || p.at(T![<]) |
@@ -41,10 +41,7 @@ fn path(p: &mut Parser, mode: Mode) { | |||
41 | path_segment(p, mode, true); | 41 | path_segment(p, mode, true); |
42 | let mut qual = path.complete(p, PATH); | 42 | let mut qual = path.complete(p, PATH); |
43 | loop { | 43 | loop { |
44 | let use_tree = match p.nth(2) { | 44 | let use_tree = matches!(p.nth(2), T![*] | T!['{']); |
45 | T![*] | T!['{'] => true, | ||
46 | _ => false, | ||
47 | }; | ||
48 | if p.at(T![::]) && !use_tree { | 45 | if p.at(T![::]) && !use_tree { |
49 | let path = qual.precede(p); | 46 | let path = qual.precede(p); |
50 | p.bump(T![::]); | 47 | p.bump(T![::]); |
@@ -73,8 +70,10 @@ fn path_segment(p: &mut Parser, mode: Mode, first: bool) { | |||
73 | } | 70 | } |
74 | p.expect(T![>]); | 71 | p.expect(T![>]); |
75 | } else { | 72 | } else { |
73 | let mut empty = true; | ||
76 | if first { | 74 | if first { |
77 | p.eat(T![::]); | 75 | p.eat(T![::]); |
76 | empty = false; | ||
78 | } | 77 | } |
79 | match p.current() { | 78 | match p.current() { |
80 | IDENT => { | 79 | IDENT => { |
@@ -86,6 +85,12 @@ fn path_segment(p: &mut Parser, mode: Mode, first: bool) { | |||
86 | T![self] | T![super] | T![crate] => p.bump_any(), | 85 | T![self] | T![super] | T![crate] => p.bump_any(), |
87 | _ => { | 86 | _ => { |
88 | p.err_recover("expected identifier", items::ITEM_RECOVERY_SET); | 87 | p.err_recover("expected identifier", items::ITEM_RECOVERY_SET); |
88 | if empty { | ||
89 | // test_err empty_segment | ||
90 | // use crate::; | ||
91 | m.abandon(p); | ||
92 | return; | ||
93 | } | ||
89 | } | 94 | } |
90 | }; | 95 | }; |
91 | } | 96 | } |
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index 68fb2fc73..427c0eb49 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs | |||
@@ -4,7 +4,7 @@ use super::*; | |||
4 | 4 | ||
5 | pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST | 5 | pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST |
6 | .union(paths::PATH_FIRST) | 6 | .union(paths::PATH_FIRST) |
7 | .union(token_set![BOX_KW, REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS, DOT]); | 7 | .union(token_set![T![box], T![ref], T![mut], T!['('], T!['['], T![&], T![_], T![-], T![.]]); |
8 | 8 | ||
9 | pub(crate) fn pattern(p: &mut Parser) { | 9 | pub(crate) fn pattern(p: &mut Parser) { |
10 | pattern_r(p, PAT_RECOVERY_SET); | 10 | pattern_r(p, PAT_RECOVERY_SET); |
@@ -88,7 +88,9 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { | |||
88 | _ => bind_pat(p, true), | 88 | _ => bind_pat(p, true), |
89 | }, | 89 | }, |
90 | 90 | ||
91 | _ if paths::is_use_path_start(p) => path_or_macro_pat(p), | 91 | // test type_path_in_pattern |
92 | // fn main() { let <_>::Foo = (); } | ||
93 | _ if paths::is_path_start(p) => path_or_macro_pat(p), | ||
92 | _ if is_literal_pat_start(p) => literal_pat(p), | 94 | _ if is_literal_pat_start(p) => literal_pat(p), |
93 | 95 | ||
94 | T![.] if p.at(T![..]) => dot_dot_pat(p), | 96 | T![.] if p.at(T![..]) => dot_dot_pat(p), |
@@ -138,7 +140,7 @@ fn literal_pat(p: &mut Parser) -> CompletedMarker { | |||
138 | // let Bar(..) = (); | 140 | // let Bar(..) = (); |
139 | // } | 141 | // } |
140 | fn path_or_macro_pat(p: &mut Parser) -> CompletedMarker { | 142 | fn path_or_macro_pat(p: &mut Parser) -> CompletedMarker { |
141 | assert!(paths::is_use_path_start(p)); | 143 | assert!(paths::is_path_start(p)); |
142 | let m = p.start(); | 144 | let m = p.start(); |
143 | paths::expr_path(p); | 145 | paths::expr_path(p); |
144 | let kind = match p.current() { | 146 | let kind = match p.current() { |
diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs index 50e4900c3..d1330d4b9 100644 --- a/crates/ra_parser/src/grammar/type_params.rs +++ b/crates/ra_parser/src/grammar/type_params.rs | |||
@@ -169,10 +169,7 @@ fn is_where_predicate(p: &mut Parser) -> bool { | |||
169 | } | 169 | } |
170 | 170 | ||
171 | fn is_where_clause_end(p: &mut Parser) -> bool { | 171 | fn is_where_clause_end(p: &mut Parser) -> bool { |
172 | match p.current() { | 172 | matches!(p.current(), T!['{'] | T![;] | T![=]) |
173 | T!['{'] | T![;] | T![=] => true, | ||
174 | _ => false, | ||
175 | } | ||
176 | } | 173 | } |
177 | 174 | ||
178 | fn where_predicate(p: &mut Parser) { | 175 | fn where_predicate(p: &mut Parser) { |
@@ -191,10 +188,14 @@ fn where_predicate(p: &mut Parser) { | |||
191 | } | 188 | } |
192 | _ => { | 189 | _ => { |
193 | // test where_pred_for | 190 | // test where_pred_for |
194 | // fn test<F>() | 191 | // fn for_trait<F>() |
195 | // where | 192 | // where |
196 | // for<'a> F: Fn(&'a str) | 193 | // for<'a> F: Fn(&'a str) |
197 | // { } | 194 | // { } |
195 | if p.at(T![for]) { | ||
196 | types::for_binder(p); | ||
197 | } | ||
198 | |||
198 | types::type_(p); | 199 | types::type_(p); |
199 | 200 | ||
200 | if p.at(T![:]) { | 201 | if p.at(T![:]) { |
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs index fe1a039cb..9e8e3bd97 100644 --- a/crates/ra_parser/src/grammar/types.rs +++ b/crates/ra_parser/src/grammar/types.rs | |||
@@ -216,19 +216,21 @@ pub(super) fn for_binder(p: &mut Parser) { | |||
216 | 216 | ||
217 | // test for_type | 217 | // test for_type |
218 | // type A = for<'a> fn() -> (); | 218 | // type A = for<'a> fn() -> (); |
219 | // fn foo<T>(_t: &T) where for<'a> &'a T: Iterator {} | 219 | // type B = for<'a> unsafe extern "C" fn(&'a ()) -> (); |
220 | // fn bar<T>(_t: &T) where for<'a> &'a mut T: Iterator {} | 220 | // type Obj = for<'a> PartialEq<&'a i32>; |
221 | // fn baz<T>(_t: &T) where for<'a> <&'a T as Baz>::Foo: Iterator {} | ||
222 | pub(super) fn for_type(p: &mut Parser) { | 221 | pub(super) fn for_type(p: &mut Parser) { |
223 | assert!(p.at(T![for])); | 222 | assert!(p.at(T![for])); |
224 | let m = p.start(); | 223 | let m = p.start(); |
225 | for_binder(p); | 224 | for_binder(p); |
226 | match p.current() { | 225 | match p.current() { |
227 | T![fn] | T![unsafe] | T![extern] => fn_pointer_type(p), | 226 | T![fn] | T![unsafe] | T![extern] => {} |
228 | T![&] => reference_type(p), | 227 | // OK: legacy trait object format |
229 | _ if paths::is_path_start(p) => path_type_(p, false), | 228 | _ if paths::is_use_path_start(p) => {} |
230 | _ => p.error("expected a path"), | 229 | _ => { |
230 | p.error("expected a function pointer or path"); | ||
231 | } | ||
231 | } | 232 | } |
233 | type_no_bounds(p); | ||
232 | m.complete(p, FOR_TYPE); | 234 | m.complete(p, FOR_TYPE); |
233 | } | 235 | } |
234 | 236 | ||
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs index 4f59b0a23..d797f2cc9 100644 --- a/crates/ra_parser/src/parser.rs +++ b/crates/ra_parser/src/parser.rs | |||
@@ -127,17 +127,24 @@ impl<'t> Parser<'t> { | |||
127 | 127 | ||
128 | fn at_composite2(&self, n: usize, k1: SyntaxKind, k2: SyntaxKind) -> bool { | 128 | fn at_composite2(&self, n: usize, k1: SyntaxKind, k2: SyntaxKind) -> bool { |
129 | let t1 = self.token_source.lookahead_nth(n); | 129 | let t1 = self.token_source.lookahead_nth(n); |
130 | if t1.kind != k1 || !t1.is_jointed_to_next { | ||
131 | return false; | ||
132 | } | ||
130 | let t2 = self.token_source.lookahead_nth(n + 1); | 133 | let t2 = self.token_source.lookahead_nth(n + 1); |
131 | t1.kind == k1 && t1.is_jointed_to_next && t2.kind == k2 | 134 | t2.kind == k2 |
132 | } | 135 | } |
133 | 136 | ||
134 | fn at_composite3(&self, n: usize, k1: SyntaxKind, k2: SyntaxKind, k3: SyntaxKind) -> bool { | 137 | fn at_composite3(&self, n: usize, k1: SyntaxKind, k2: SyntaxKind, k3: SyntaxKind) -> bool { |
135 | let t1 = self.token_source.lookahead_nth(n); | 138 | let t1 = self.token_source.lookahead_nth(n); |
139 | if t1.kind != k1 || !t1.is_jointed_to_next { | ||
140 | return false; | ||
141 | } | ||
136 | let t2 = self.token_source.lookahead_nth(n + 1); | 142 | let t2 = self.token_source.lookahead_nth(n + 1); |
143 | if t2.kind != k2 || !t2.is_jointed_to_next { | ||
144 | return false; | ||
145 | } | ||
137 | let t3 = self.token_source.lookahead_nth(n + 2); | 146 | let t3 = self.token_source.lookahead_nth(n + 2); |
138 | (t1.kind == k1 && t1.is_jointed_to_next) | 147 | t3.kind == k3 |
139 | && (t2.kind == k2 && t2.is_jointed_to_next) | ||
140 | && t3.kind == k3 | ||
141 | } | 148 | } |
142 | 149 | ||
143 | /// Checks if the current token is in `kinds`. | 150 | /// Checks if the current token is in `kinds`. |
diff --git a/crates/ra_parser/src/syntax_kind.rs b/crates/ra_parser/src/syntax_kind.rs index 8d6bd057b..63204436c 100644 --- a/crates/ra_parser/src/syntax_kind.rs +++ b/crates/ra_parser/src/syntax_kind.rs | |||
@@ -20,9 +20,6 @@ impl From<SyntaxKind> for u16 { | |||
20 | 20 | ||
21 | impl SyntaxKind { | 21 | impl SyntaxKind { |
22 | pub fn is_trivia(self) -> bool { | 22 | pub fn is_trivia(self) -> bool { |
23 | match self { | 23 | matches!(self, SyntaxKind::WHITESPACE | SyntaxKind::COMMENT) |
24 | SyntaxKind::WHITESPACE | SyntaxKind::COMMENT => true, | ||
25 | _ => false, | ||
26 | } | ||
27 | } | 24 | } |
28 | } | 25 | } |