Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/parser/src/grammar/generic_args.rs')
| -rw-r--r-- | crates/parser/src/grammar/generic_args.rs | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/crates/parser/src/grammar/generic_args.rs b/crates/parser/src/grammar/generic_args.rs new file mode 100644 index 0000000000..cd75d20a42 --- /dev/null +++ b/crates/parser/src/grammar/generic_args.rs @@ -0,0 +1,139 @@ +use super::*; + +pub(super) fn opt_generic_arg_list(p: &mut Parser, colon_colon_required: bool) { + let m; + if p.at(T![::]) && p.nth(2) == T![<] { + m = p.start(); + p.bump(T![::]); + p.bump(T![<]); + } else if !colon_colon_required && p.at(T![<]) && p.nth(1) != T![=] { + m = p.start(); + p.bump(T![<]); + } else { + return; + } + + while !p.at(EOF) && !p.at(T![>]) { + generic_arg(p); + if !p.at(T![>]) && !p.expect(T![,]) { + break; + } + } + p.expect(T![>]); + m.complete(p, GENERIC_ARG_LIST); +} + +// test type_arg +// type A = B<'static, i32, 1, { 2 }, Item=u64, true, false>; +fn generic_arg(p: &mut Parser) { + let m = p.start(); + match p.current() { + LIFETIME_IDENT => { + lifetime(p); + m.complete(p, LIFETIME_ARG); + } + // test associated_type_bounds + // fn print_all<T: Iterator<Item, Item::Item, Item::<true>, Item: Display, Item<'a> = Item>>(printables: T) {} + IDENT if [T![<], T![=], T![:]].contains(&p.nth(1)) => { + let path_ty = p.start(); + let path = p.start(); + let path_seg = p.start(); + name_ref(p); + opt_generic_arg_list(p, false); + match p.current() { + // NameRef<...> = + T![=] => { + p.bump_any(); + types::type_(p); + + path_seg.abandon(p); + path.abandon(p); + path_ty.abandon(p); + m.complete(p, ASSOC_TYPE_ARG); + } + T![:] if p.at(T![::]) => { + // NameRef::, this is a path type + path_seg.complete(p, PATH_SEGMENT); + let qual = path.complete(p, PATH); + opt_generic_arg_list(p, false); + paths::type_path_for_qualifier(p, qual); + path_ty.complete(p, PATH_TYPE); + m.complete(p, TYPE_ARG); + } + // NameRef<...>: + T![:] => { + generic_params::bounds(p); + + path_seg.abandon(p); + path.abandon(p); + path_ty.abandon(p); + m.complete(p, ASSOC_TYPE_ARG); + } + // NameRef, this is a single segment path type + _ => { + path_seg.complete(p, PATH_SEGMENT); + path.complete(p, PATH); + path_ty.complete(p, PATH_TYPE); + m.complete(p, TYPE_ARG); + } + } + } + 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); + } + // test const_generic_negated_literal + // fn f() { S::<-1> } + T![-] => { + let lm = p.start(); + p.bump(T![-]); + expressions::literal(p); + lm.complete(p, PREFIX_EXPR); + m.complete(p, CONST_ARG); + } + _ => { + types::type_(p); + m.complete(p, TYPE_ARG); + } + } +} + +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); + } + } +} |