grammar: for predicates in where

closes #191
This commit is contained in:
Aleksey Kladov 2018-11-05 11:24:02 +03:00
parent 576b9a0727
commit 9010cb9839
4 changed files with 130 additions and 36 deletions

View File

@ -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;

View File

@ -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();
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<T = i32>;
if p.at(EQ) {
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<T = i32>;
if p.at(EQ) {
p.bump();
types::type_(p)
}
m.complete(p, TYPE_PARAM);
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");
}
}
} else {
types::path_type(p);
if p.at(COLON) {
bounds(p);
} else {
p.error("expected colon")
// test where_pred_for
// fn test<F>()
// 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 `<`");
}
}
_ => {
types::path_type(p);
if p.at(COLON) {
bounds(p);
} else {
p.error("expected colon");
}
}
}
m.complete(p, WHERE_PRED);

View File

@ -0,0 +1,4 @@
fn test<F>()
where
for<'a> F: Fn(&'a str)
{ }

View File

@ -0,0 +1,58 @@
ROOT@[0; 49)
FN_DEF@[0; 48)
FN_KW@[0; 2)
WHITESPACE@[2; 3)
NAME@[3; 7)
IDENT@[3; 7) "test"
TYPE_PARAM_LIST@[7; 10)
L_ANGLE@[7; 8)
TYPE_PARAM@[8; 9)
NAME@[8; 9)
IDENT@[8; 9) "F"
R_ANGLE@[9; 10)
PARAM_LIST@[10; 12)
L_PAREN@[10; 11)
R_PAREN@[11; 12)
WHITESPACE@[12; 13)
WHERE_CLAUSE@[13; 44)
WHERE_KW@[13; 18)
WHITESPACE@[18; 22)
WHERE_PRED@[22; 44)
FOR_KW@[22; 25)
TYPE_PARAM_LIST@[25; 29)
L_ANGLE@[25; 26)
LIFETIME_PARAM@[26; 28)
LIFETIME@[26; 28) "'a"
R_ANGLE@[28; 29)
WHITESPACE@[29; 30)
PATH_TYPE@[30; 31)
PATH@[30; 31)
PATH_SEGMENT@[30; 31)
NAME_REF@[30; 31)
IDENT@[30; 31) "F"
COLON@[31; 32)
WHITESPACE@[32; 33)
PATH_TYPE@[33; 44)
PATH@[33; 44)
PATH_SEGMENT@[33; 44)
NAME_REF@[33; 35)
IDENT@[33; 35) "Fn"
PARAM_LIST@[35; 44)
L_PAREN@[35; 36)
PARAM@[36; 43)
REFERENCE_TYPE@[36; 43)
AMP@[36; 37)
LIFETIME@[37; 39) "'a"
WHITESPACE@[39; 40)
PATH_TYPE@[40; 43)
PATH@[40; 43)
PATH_SEGMENT@[40; 43)
NAME_REF@[40; 43)
IDENT@[40; 43) "str"
R_PAREN@[43; 44)
WHITESPACE@[44; 45)
BLOCK@[45; 48)
L_CURLY@[45; 46)
WHITESPACE@[46; 47)
R_CURLY@[47; 48)
WHITESPACE@[48; 49)