parent
576b9a0727
commit
9010cb9839
4 changed files with 130 additions and 36 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
fn test<F>()
|
||||
where
|
||||
for<'a> F: Fn(&'a str)
|
||||
{ }
|
|
@ -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)
|
Loading…
Add table
Reference in a new issue