From 9010cb98399dad6be845f9a143a466ca51b5798f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 5 Nov 2018 11:24:02 +0300 Subject: grammar: for predicates in where closes #191 --- crates/ra_syntax/src/grammar/mod.rs | 5 ++ crates/ra_syntax/src/grammar/type_params.rs | 97 ++++++++++++++++++----------- 2 files changed, 67 insertions(+), 35 deletions(-) (limited to 'crates/ra_syntax/src/grammar') 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 @@ //! After adding a new inline-test, run `cargo collect-tests` to extract //! it as a standalone text-fixture into `tests/data/parser/inline`, and //! run `cargo test` once to create the "gold" value. +//! +//! Coding convention: rules like `where_clause` always produce either a +//! node or an error, rules like `opt_where_clause` may produce nothing. +//! Non-opt rules typically start with `assert!(p.at(FIRST_TOKEN))`, the +//! caller is responsible for branching on the first token. mod attributes; mod expressions; mod items; diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs index 79f5036b4..735c728e5 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) { if !p.at(L_ANGLE) { return; } + type_param_list(p); +} + +fn type_param_list(p: &mut Parser) { + assert!(p.at(L_ANGLE)); let m = p.start(); p.bump(); @@ -19,32 +24,32 @@ pub(super) fn opt_type_param_list(p: &mut Parser) { } p.expect(R_ANGLE); m.complete(p, TYPE_PARAM_LIST); +} - fn lifetime_param(p: &mut Parser) { - assert!(p.at(LIFETIME)); - let m = p.start(); - p.bump(); - if p.at(COLON) { - lifetime_bounds(p); - } - m.complete(p, LIFETIME_PARAM); +fn lifetime_param(p: &mut Parser) { + assert!(p.at(LIFETIME)); + let m = p.start(); + p.bump(); + if p.at(COLON) { + lifetime_bounds(p); } + m.complete(p, LIFETIME_PARAM); +} - fn type_param(p: &mut Parser) { - assert!(p.at(IDENT)); - let m = p.start(); - name(p); - if p.at(COLON) { - bounds(p); - } - // test type_param_default - // struct S; - if p.at(EQ) { - p.bump(); - types::type_(p) - } - m.complete(p, TYPE_PARAM); +fn type_param(p: &mut Parser) { + assert!(p.at(IDENT)); + let m = p.start(); + name(p); + if p.at(COLON) { + bounds(p); + } + // test type_param_default + // struct S; + if p.at(EQ) { + p.bump(); + types::type_(p) } + m.complete(p, TYPE_PARAM); } // test type_param_bounds @@ -99,7 +104,7 @@ pub(super) fn opt_where_clause(p: &mut Parser) { let m = p.start(); p.bump(); loop { - if !(paths::is_path_start(p) || p.current() == LIFETIME) { + if !(paths::is_path_start(p) || p.current() == LIFETIME || p.current() == FOR_KW) { break; } where_predicate(p); @@ -112,19 +117,41 @@ pub(super) fn opt_where_clause(p: &mut Parser) { fn where_predicate(p: &mut Parser) { let m = p.start(); - if p.at(LIFETIME) { - p.eat(LIFETIME); - if p.at(COLON) { - lifetime_bounds(p) - } else { - p.error("expected colon") + match p.current() { + LIFETIME => { + p.bump(); + if p.at(COLON) { + lifetime_bounds(p); + } else { + p.error("expected colon"); + } + } + // test where_pred_for + // fn test() + // where + // for<'a> F: Fn(&'a str) + // { } + FOR_KW => { + p.bump(); + if p.at(L_ANGLE) { + type_param_list(p); + types::path_type(p); + if p.at(COLON) { + bounds(p); + } else { + p.error("expected colon"); + } + } else { + p.error("expected `<`"); + } } - } else { - types::path_type(p); - if p.at(COLON) { - bounds(p); - } else { - p.error("expected colon") + _ => { + types::path_type(p); + if p.at(COLON) { + bounds(p); + } else { + p.error("expected colon"); + } } } m.complete(p, WHERE_PRED); -- cgit v1.2.3