Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/parser/src/grammar/paths.rs')
| -rw-r--r-- | crates/parser/src/grammar/paths.rs | 175 |
1 files changed, 109 insertions, 66 deletions
diff --git a/crates/parser/src/grammar/paths.rs b/crates/parser/src/grammar/paths.rs index 09db921803..3410505cd4 100644 --- a/crates/parser/src/grammar/paths.rs +++ b/crates/parser/src/grammar/paths.rs @@ -19,6 +19,14 @@ pub(super) fn use_path(p: &mut Parser<'_>) { path(p, Mode::Use); } +pub(super) fn vis_path(p: &mut Parser<'_>) { + path(p, Mode::Vis); +} + +pub(super) fn attr_path(p: &mut Parser<'_>) { + path(p, Mode::Attr); +} + pub(crate) fn type_path(p: &mut Parser<'_>) { path(p, Mode::Type); } @@ -37,15 +45,20 @@ pub(crate) fn type_path_for_qualifier( #[derive(Clone, Copy, Eq, PartialEq)] enum Mode { Use, + Attr, Type, Expr, + Vis, } -fn path(p: &mut Parser<'_>, mode: Mode) { +fn path(p: &mut Parser<'_>, mode: Mode) -> Option<CompletedMarker> { let path = p.start(); - path_segment(p, mode, true); + if path_segment(p, mode, true).is_none() { + path.abandon(p); + return None; + } let qual = path.complete(p, PATH); - path_for_qualifier(p, mode, qual); + Some(path_for_qualifier(p, mode, qual)) } fn path_for_qualifier( @@ -71,7 +84,7 @@ const EXPR_PATH_SEGMENT_RECOVERY_SET: TokenSet = items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')'], T![,], T![let]])); const TYPE_PATH_SEGMENT_RECOVERY_SET: TokenSet = types::TYPE_RECOVERY_SET; -fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) { +fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<CompletedMarker> { let m = p.start(); // test qual_paths // type X = <A as B>::Output; @@ -93,75 +106,105 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) { p.error("expected `::`"); } } else { - let empty = if first { - p.eat(T![::]); - false - } else { - true - }; - match p.current() { - IDENT => { - name_ref(p); - opt_path_type_args(p, mode); - } + let mut empty = if first { !p.eat(T![::]) } else { true }; + if p.at_ts(PATH_NAME_REF_KINDS) { // test crate_path // use crate::foo; - T![self] | T![super] | T![crate] | T![Self] => { - let m = p.start(); - p.bump_any(); - m.complete(p, NAME_REF); - } - _ => { - let recover_set = match mode { - Mode::Use => items::ITEM_RECOVERY_SET, - Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET, - Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET, - }; - p.err_recover("expected identifier", recover_set); - if empty { - // test_err empty_segment - // use crate::; - m.abandon(p); - return; + name_ref_mod_path(p); + opt_path_args(p, mode); + } else { + let recover_set = match mode { + Mode::Use => items::ITEM_RECOVERY_SET, + Mode::Attr => { + items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![']'], T![=], T![#]])) } + Mode::Vis => items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')']])), + Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET, + Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET, + }; + empty &= p.err_recover( + "expected identifier, `self`, `super`, `crate`, or `Self`", + recover_set, + ); + if empty { + // test_err empty_segment + // use crate::; + m.abandon(p); + return None; } - }; + } } - m.complete(p, PATH_SEGMENT); + Some(m.complete(p, PATH_SEGMENT)) } -fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) { +pub(crate) fn opt_path_type_args(p: &mut Parser<'_>) { + // test typepathfn_with_coloncolon + // type F = Start::(Middle) -> (Middle)::End; + // type GenericArg = S<Start(Middle)::End>; + let m; + if p.at(T![::]) && matches!(p.nth(2), T![<] | T!['(']) { + m = p.start(); + p.bump(T![::]); + } else if (p.current() == T![<] && p.nth(1) != T![=]) || p.current() == T!['('] { + m = p.start(); + } else { + return; + } + let current = p.current(); + if current == T![<] { + // test_err generic_arg_list_recover + // type T = T<0, ,T>; + // type T = T::<0, ,T>; + delimited( + p, + T![<], + T![>], + T![,], + || "expected generic argument".into(), + generic_args::GENERIC_ARG_FIRST, + generic_args::generic_arg, + ); + m.complete(p, GENERIC_ARG_LIST); + } else if p.nth_at(1, T![..]) { + // test return_type_syntax_in_path + // fn foo<T>() + // where + // T::method(..): Send, + // method(..): Send, + // method::(..): Send, + // {} + p.bump(T!['(']); + p.bump(T![..]); + p.expect(T![')']); + m.complete(p, RETURN_TYPE_SYNTAX); + } else { + // test path_fn_trait_args + // type F = Box<Fn(i32) -> ()>; + // type F = Box<::Fn(i32) -> ()>; + // type F = Box<Fn::(i32) -> ()>; + // type F = Box<::Fn::(i32) -> ()>; + delimited( + p, + T!['('], + T![')'], + T![,], + || "expected type".into(), + types::TYPE_FIRST, + |p| { + let progress = types::TYPE_FIRST.contains(p.current()); + generic_args::type_arg(p); + progress + }, + ); + m.complete(p, PARENTHESIZED_ARG_LIST); + opt_ret_type(p); + } +} + +fn opt_path_args(p: &mut Parser<'_>, mode: Mode) { match mode { - Mode::Use => {} - Mode::Type => { - // test typepathfn_with_coloncolon - // type F = Start::(Middle) -> (Middle)::End; - // type GenericArg = S<Start(Middle)::End>; - if p.at(T![::]) && p.nth_at(2, T!['(']) { - p.bump(T![::]); - } - if p.at(T!['(']) { - if p.nth_at(1, T![..]) { - // test return_type_syntax_in_path - // fn foo<T>() - // where - // T::method(..): Send, - // {} - let rtn = p.start(); - p.bump(T!['(']); - p.bump(T![..]); - p.expect(T![')']); - rtn.complete(p, RETURN_TYPE_SYNTAX); - } else { - // test path_fn_trait_args - // type F = Box<Fn(i32) -> ()>; - params::param_list_fn_trait(p); - opt_ret_type(p); - } - } else { - generic_args::opt_generic_arg_list(p, false); - } - } - Mode::Expr => generic_args::opt_generic_arg_list(p, true), + Mode::Use | Mode::Attr | Mode::Vis => {} + Mode::Type => opt_path_type_args(p), + Mode::Expr => generic_args::opt_generic_arg_list_expr(p), } } |