/// Parse the suffix to a name. IEEE 1076-2008 section 8.
///
/// ```text
/// name
///   := primary_name
///   := name "." (ident | char_lit | string_lit | "all")
///   := name [signature] "'" ident
///   := name paren_expr
/// ```
Parse the suffix to a name.
Parse the suffix to a name .
pub fn parse_name_suffix<P: Parser>(
    p: &mut P,
    mut name: ast::CompoundName,
) -> ReportedResult<ast::CompoundName> {
    // Try to parse a selected name.
    if accept(p, Period) {
        // Parse the suffix, which is a primary name or the keyword `all`.
        let suffix = {
            if let Some(pn) = try_primary_name(p) {
                ast::NamePart::Select(pn)
            } else {
                // `else if accept(...)` breaks on rust 1.15: p borrowed mutably in pattern guard
                if accept(p, Keyword(Kw::All)) {
                    ast::NamePart::SelectAll(p.last_span())
                } else {
                    let Spanned { value: wrong, span } = p.peek(0);
                    p.emit(
                        DiagBuilder2::error(
                            "Expected identifier, character literal, operator symbol, or `all` \
                             after `.`",
                        )
                        .span(span)
                        .add_note("see IEEE 1076-2008 section 8.3"),
                    );
                    return Err(Reported);
                }
            }
        };
        // Extend the name
        name.span.expand(p.last_span());
        name.parts.push(suffix);
        return parse_name_suffix(p, name);
    }
    // Try to parse a signature.
    if let Some(sig) = try_flanked(p, Brack, parse_signature)? {
        name.span.expand(p.last_span());
        name.parts.push(ast::NamePart::Signature(sig));
        return parse_name_suffix(p, name);
    }
    // Try to parse an attribute name.
    if p.peek(0).value == Apostrophe && p.peek(1).value != OpenDelim(Paren) {
        require(p, Apostrophe)?;
        // Unfortunately `range` is a valid attribute name, even though it is
        // defined as a language keyword. The solution here is quite hacky, but
        // works: We generate a "range" name on the fly and return it as
        // attribute name. The downside is that we lose the capitalization that
        // was present in the source text, which might confuse the user.
        let attr = if accept(p, Keyword(Kw::Range)) {
            Spanned::new(get_name_table().intern("range", false), p.last_span())
        } else {
            parse_ident(p, "attribute name")?
        };
        name.span.expand(p.last_span());
        name.parts.push(ast::NamePart::Attribute(attr.into()));
        return parse_name_suffix(p, name);
    }
    // Try to parse a function call, slice name, or indexed name.
    if let Some(al) = try_paren_expr(p)? {
        name.span.expand(p.last_span());
        name.parts.push(ast::NamePart::Call(al));
        return parse_name_suffix(p, name);
    }
    // Try to parse a range constraint.
    if accept(p, Keyword(Kw::Range)) {
        let expr = parse_expr_prec(p, ExprPrec::Range)?;
        name.parts.push(ast::NamePart::Range(Box::new(expr)));
        name.span.expand(p.last_span());
        return parse_name_suffix(p, name);
    }
    // If we arrive here, none of the suffices matched, and we simply return the
    // prefix that we have received.
    Ok(name)
}
pub fn parse_name_suffix < P : Parser > ( p : & mut P , mut name : ast :: CompoundName , ) -> ReportedResult < ast :: CompoundName > { // Try to parse a selected name. if accept ( p , Period ) { // Parse the suffix, which is a primary name or the keyword `all`. let suffix = { if let Some ( pn ) = try_primary_name ( p ) { ast :: NamePart :: Select ( pn ) } else { // `else if accept(...)` breaks on rust 1.15: p borrowed mutably in pattern guard if accept ( p , Keyword ( Kw :: All ) ) { ast :: NamePart :: SelectAll ( p . last_span ( ) ) } else { let Spanned { value : wrong , span } = p . peek ( 0 ) ; p . emit ( DiagBuilder2 :: error ( " \
 " , ) . span ( span ) . add_note ( " " ) , ) ; return Err ( Reported ) ; } } } ; // Extend the name name . span . expand ( p . last_span ( ) ) ; name . parts . push ( suffix ) ; return parse_name_suffix ( p , name ) ; } // Try to parse a signature. if let Some ( sig ) = try_flanked ( p , Brack , parse_signature ) ? { name . span . expand ( p . last_span ( ) ) ; name . parts . push ( ast :: NamePart :: Signature ( sig ) ) ; return parse_name_suffix ( p , name ) ; } // Try to parse an attribute name. if p . peek ( 0 ) . value == Apostrophe && p . peek ( 1 ) . value != OpenDelim ( Paren ) { require ( p , Apostrophe ) ? ; // Unfortunately `range` is a valid attribute name, even though it is // defined as a language keyword. The solution here is quite hacky, but // works: We generate a "range" name on the fly and return it as // attribute name. The downside is that we lose the capitalization that // was present in the source text, which might confuse the user. let attr = if accept ( p , Keyword ( Kw :: Range ) ) { Spanned :: new ( get_name_table ( ) . intern ( " " , false ) , p . last_span ( ) ) } else { parse_ident ( p , " " ) ? } ; name . span . expand ( p . last_span ( ) ) ; name . parts . push ( ast :: NamePart :: Attribute ( attr . into ( ) ) ) ; return parse_name_suffix ( p , name ) ; } // Try to parse a function call, slice name, or indexed name. if let Some ( al ) = try_paren_expr ( p ) ? { name . span . expand ( p . last_span ( ) ) ; name . parts . push ( ast :: NamePart :: Call ( al ) ) ; return parse_name_suffix ( p , name ) ; } // Try to parse a range constraint. if accept ( p , Keyword ( Kw :: Range ) ) { let expr = parse_expr_prec ( p , ExprPrec :: Range ) ? ; name . parts . push ( ast :: NamePart :: Range ( Box :: new ( expr ) ) ) ; name . span . expand ( p . last_span ( ) ) ; return parse_name_suffix ( p , name ) ; } // If we arrive here, none of the suffices matched, and we simply return the // prefix that we have received. Ok ( name ) }
Parse the suffix to a name.
Parse the suffix to a name .
p
&mut P
name
ast::CompoundName