Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/parser/src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ mod items;
mod params;
mod paths;
mod patterns;
mod type_args;
mod type_params;
mod generic_args;
mod generic_params;
mod types;

use crate::{
Expand Down
2 changes: 1 addition & 1 deletion crates/parser/src/grammar/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
let m = lhs.precede(p);
p.bump_any();
name_ref(p);
type_args::opt_generic_arg_list(p, true);
generic_args::opt_generic_arg_list(p, true);
if p.at(T!['(']) {
arg_list(p);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,38 +23,6 @@ pub(super) fn opt_generic_arg_list(p: &mut Parser, colon_colon_required: bool) {
m.complete(p, GENERIC_ARG_LIST);
}

pub(super) fn const_arg(p: &mut Parser) {
let m = p.start();
// FIXME: duplicates the code below
match p.current() {
T!['{'] => {
expressions::block_expr(p);
m.complete(p, CONST_ARG);
}
k if k.is_literal() => {
expressions::literal(p);
m.complete(p, CONST_ARG);
}
T![true] | T![false] => {
expressions::literal(p);
m.complete(p, CONST_ARG);
}
T![-] => {
let lm = p.start();
p.bump(T![-]);
expressions::literal(p);
lm.complete(p, PREFIX_EXPR);
m.complete(p, CONST_ARG);
}
_ => {
let lm = p.start();
paths::use_path(p);
lm.complete(p, PATH_EXPR);
m.complete(p, CONST_ARG);
}
}
}

// test type_arg
// type A = B<'static, i32, 1, { 2 }, Item=u64, true, false>;
fn generic_arg(p: &mut Parser) {
Expand Down Expand Up @@ -83,7 +51,7 @@ fn generic_arg(p: &mut Parser) {
path_ty.abandon(p);
m.complete(p, ASSOC_TYPE_ARG);
}
T![:] if p.nth(1) == T![:] => {
T![:] if p.at(T![::]) => {
// NameRef::, this is a path type
path_seg.complete(p, PATH_SEGMENT);
let qual = path.complete(p, PATH);
Expand All @@ -94,7 +62,7 @@ fn generic_arg(p: &mut Parser) {
}
// NameRef<...>:
T![:] => {
type_params::bounds(p);
generic_params::bounds(p);

path_seg.abandon(p);
path.abandon(p);
Expand Down Expand Up @@ -137,3 +105,35 @@ fn generic_arg(p: &mut Parser) {
}
}
}

pub(super) fn const_arg(p: &mut Parser) {
let m = p.start();
// FIXME: duplicates the code above
match p.current() {
T!['{'] => {
expressions::block_expr(p);
m.complete(p, CONST_ARG);
}
k if k.is_literal() => {
expressions::literal(p);
m.complete(p, CONST_ARG);
}
T![true] | T![false] => {
expressions::literal(p);
m.complete(p, CONST_ARG);
}
T![-] => {
let lm = p.start();
p.bump(T![-]);
expressions::literal(p);
lm.complete(p, PREFIX_EXPR);
m.complete(p, CONST_ARG);
}
_ => {
let lm = p.start();
paths::use_path(p);
lm.complete(p, PATH_EXPR);
m.complete(p, CONST_ARG);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,20 @@
use super::*;

pub(super) fn opt_generic_param_list(p: &mut Parser) {
if !p.at(T![<]) {
return;
if p.at(T![<]) {
generic_param_list(p);
}
generic_param_list(p);
}

// test generic_param_list
// fn f<T: Clone>() {}
fn generic_param_list(p: &mut Parser) {
assert!(p.at(T![<]));
let m = p.start();
p.bump(T![<]);

while !p.at(EOF) && !p.at(T![>]) {
let m = p.start();

// test generic_lifetime_type_attribute
// fn foo<#[derive(Lifetime)] 'a, #[derive(Type)] T>(_: &'a T) {
// }
attributes::outer_attrs(p);

match p.current() {
LIFETIME_IDENT => lifetime_param(p, m),
IDENT => type_param(p, m),
T![const] => const_param(p, m),
_ => {
m.abandon(p);
p.err_and_bump("expected type parameter")
}
}
generic_param(p);
if !p.at(T![>]) && !p.expect(T![,]) {
break;
}
Expand All @@ -37,6 +23,24 @@ fn generic_param_list(p: &mut Parser) {
m.complete(p, GENERIC_PARAM_LIST);
}

fn generic_param(p: &mut Parser) {
let m = p.start();
// test generic_param_attribute
// fn foo<#[lt_attr] 'a, #[t_attr] T>() {}
attributes::outer_attrs(p);
match p.current() {
LIFETIME_IDENT => lifetime_param(p, m),
IDENT => type_param(p, m),
T![const] => const_param(p, m),
_ => {
m.abandon(p);
p.err_and_bump("expected type parameter")
}
}
}

// test lifetime_param
// fn f<'a: 'b>() {}
fn lifetime_param(p: &mut Parser, m: Marker) {
assert!(p.at(LIFETIME_IDENT));
lifetime(p);
Expand All @@ -46,15 +50,17 @@ fn lifetime_param(p: &mut Parser, m: Marker) {
m.complete(p, LIFETIME_PARAM);
}

// test type_param
// fn f<T: Clone>() {}
fn type_param(p: &mut Parser, m: Marker) {
assert!(p.at(IDENT));
name(p);
if p.at(T![:]) {
bounds(p);
}
// test type_param_default
// struct S<T = i32>;
if p.at(T![=]) {
// test type_param_default
// struct S<T = i32>;
p.bump(T![=]);
types::type_(p)
}
Expand All @@ -64,7 +70,6 @@ fn type_param(p: &mut Parser, m: Marker) {
// test const_param
// struct S<const N: u32>;
fn const_param(p: &mut Parser, m: Marker) {
assert!(p.at(T![const]));
p.bump(T![const]);
name(p);
if p.at(T![:]) {
Expand All @@ -73,26 +78,18 @@ fn const_param(p: &mut Parser, m: Marker) {
p.error("missing type for const parameter");
}

// test const_param_defaults
// struct A<const N: i32 = -1>;
// struct B<const N: i32 = {}>;
// struct C<const N: i32 = some::CONST>;
if p.at(T![=]) {
// test const_param_defaults
// struct A<const N: i32 = -1>;
// struct B<const N: i32 = {}>;
// struct C<const N: i32 = some::CONST>;
p.bump(T![=]);
type_args::const_arg(p);
generic_args::const_arg(p);
}

m.complete(p, CONST_PARAM);
}

// test type_param_bounds
// struct S<T: 'a + ?Sized + (Copy)>;
pub(super) fn bounds(p: &mut Parser) {
assert!(p.at(T![:]));
p.bump(T![:]);
bounds_without_colon(p);
}

fn lifetime_bounds(p: &mut Parser) {
assert!(p.at(T![:]));
p.bump(T![:]);
Expand All @@ -104,21 +101,28 @@ fn lifetime_bounds(p: &mut Parser) {
}
}

// test type_param_bounds
// struct S<T: 'a + ?Sized + (Copy)>;
pub(super) fn bounds(p: &mut Parser) {
assert!(p.at(T![:]));
p.bump(T![:]);
bounds_without_colon(p);
}

pub(super) fn bounds_without_colon(p: &mut Parser) {
let m = p.start();
bounds_without_colon_m(p, m);
}

pub(super) fn bounds_without_colon_m(p: &mut Parser, marker: Marker) -> CompletedMarker {
while type_bound(p) {
if !p.eat(T![+]) {
break;
}
}

marker.complete(p, TYPE_BOUND_LIST)
}

pub(super) fn bounds_without_colon(p: &mut Parser) {
let m = p.start();
bounds_without_colon_m(p, m);
}

fn type_bound(p: &mut Parser) -> bool {
let m = p.start();
let has_paren = p.eat(T!['(']);
Expand Down Expand Up @@ -160,8 +164,9 @@ pub(super) fn opt_where_clause(p: &mut Parser) {

let comma = p.eat(T![,]);

if is_where_clause_end(p) {
break;
match p.current() {
T!['{'] | T![;] | T![=] => break,
_ => (),
}

if !comma {
Expand All @@ -170,20 +175,16 @@ pub(super) fn opt_where_clause(p: &mut Parser) {
}

m.complete(p, WHERE_CLAUSE);
}

fn is_where_predicate(p: &mut Parser) -> bool {
match p.current() {
LIFETIME_IDENT => true,
T![impl] => false,
token => types::TYPE_FIRST.contains(token),
fn is_where_predicate(p: &mut Parser) -> bool {
match p.current() {
LIFETIME_IDENT => true,
T![impl] => false,
token => types::TYPE_FIRST.contains(token),
}
}
}

fn is_where_clause_end(p: &mut Parser) -> bool {
matches!(p.current(), T!['{'] | T![;] | T![=])
}

fn where_predicate(p: &mut Parser) {
let m = p.start();
match p.current() {
Expand All @@ -199,12 +200,12 @@ fn where_predicate(p: &mut Parser) {
p.error("expected lifetime or type");
}
_ => {
// test where_pred_for
// fn for_trait<F>()
// where
// for<'a> F: Fn(&'a str)
// { }
if p.at(T![for]) {
// test where_pred_for
// fn for_trait<F>()
// where
// for<'a> F: Fn(&'a str)
// { }
types::for_binder(p);
}

Expand Down
12 changes: 6 additions & 6 deletions crates/parser/src/grammar/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use super::*;
// struct S;
pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
attributes::inner_attrs(p);
while !(stop_on_r_curly && p.at(T!['}']) || p.at(EOF)) {
while !p.at(EOF) && !(p.at(T!['}']) && stop_on_r_curly) {
item_or_macro(p, stop_on_r_curly)
}
}
Expand Down Expand Up @@ -284,15 +284,15 @@ fn type_alias(p: &mut Parser, m: Marker) {

// test type_item_type_params
// type Result<T> = ();
type_params::opt_generic_param_list(p);
generic_params::opt_generic_param_list(p);

if p.at(T![:]) {
type_params::bounds(p);
generic_params::bounds(p);
}

// test type_item_where_clause
// type Foo where Foo: Copy = ();
type_params::opt_where_clause(p);
generic_params::opt_where_clause(p);
if p.eat(T![=]) {
types::type_(p);
}
Expand Down Expand Up @@ -383,7 +383,7 @@ fn fn_(p: &mut Parser, m: Marker) {
name_r(p, ITEM_RECOVERY_SET);
// test function_type_params
// fn foo<T: Clone + Copy>(){}
type_params::opt_generic_param_list(p);
generic_params::opt_generic_param_list(p);

if p.at(T!['(']) {
params::param_list_fn_def(p);
Expand All @@ -397,7 +397,7 @@ fn fn_(p: &mut Parser, m: Marker) {

// test function_where_clause
// fn foo<T>() where T: Copy {}
type_params::opt_where_clause(p);
generic_params::opt_where_clause(p);

if p.at(T![;]) {
// test fn_decl
Expand Down
Loading