pub fn parse_subprog_spec<P: Parser>(p: &mut P) -> ReportedResult<ast::SubprogSpec> {
    let mut span = p.peek(0).span;

    // Parse the optional purity qualifier.
    let purity = match p.peek(0).value {
        Keyword(Kw::Pure) => {
            p.bump();
            Some(ast::SubprogPurity::Pure)
        }
        Keyword(Kw::Impure) => {
            p.bump();
            Some(ast::SubprogPurity::Impure)
        }
        _ => None,
    };

    // Parse the subprogram kind.
    let pk = p.peek(0);
    let kind = match pk.value {
        Keyword(Kw::Procedure) => {
            p.bump();
            ast::SubprogKind::Proc
        }
        Keyword(Kw::Function) => {
            p.bump();
            ast::SubprogKind::Func
        }
        wrong => {
            p.emit(
                DiagBuilder2::error(format!(
                    "Expected `procedure` or `function`, found {} instead",
                    wrong
                ))
                .span(span)
                .add_note("see IEEE 1076-2008 section 4.2"),
            );
            return Err(Reported);
        }
    };

    // Parse the name.
    let name = match try_primary_name(p) {
        Some(n) => n,
        None => {
            let pk = p.peek(0);
            p.emit(
                DiagBuilder2::error(format!(
                    "Expected subprogram name, found {} instead",
                    pk.value
                ))
                .span(pk.span)
                .add_note("A subprogram name is either an identifier or an operator symbol")
                .add_note("see IEEE 1076-2008 section 4.2"),
            );
            return Err(Reported);
        }
    };

    // Parse the optional generic clause.
    let gc = if p.peek(0).value == Keyword(Kw::Generic) && p.peek(1).value != Keyword(Kw::Map) {
        p.bump();
        Some(flanked(p, Paren, |p| {
            Ok(separated_nonempty(
                p,
                Semicolon,
                CloseDelim(Paren),
                "generic interface declaration",
                |p| parse_intf_decl(p, Some(ast::IntfObjKind::Const)),
            )?)
        })?)
    } else {
        None
    };

    // Parse the optional generic map aspect.
    let gm = try_map_aspect(p, Kw::Generic)?;

    // Parse the optional parameter keyword and list.
    let params = if accept(p, Keyword(Kw::Parameter)) || p.peek(0).value == OpenDelim(Paren) {
        Some(flanked(p, Paren, |p| {
            Ok(separated_nonempty(
                p,
                Semicolon,
                CloseDelim(Paren),
                "parameter interface declaration",
                |p| parse_intf_decl(p, Some(ast::IntfObjKind::Var)),
            )?)
        })?)
    } else {
        None
    };

    // Parse the optional return type.
    let retty = if accept(p, Keyword(Kw::Return)) {
        Some(parse_name(p)?)
    } else {
        None
    };

    span.expand(p.last_span());
    Ok(ast::SubprogSpec {
        span: span,
        name: name,
        kind: kind,
        purity: purity,
        generic_clause: gc,
        generic_map: gm,
        params: params,
        retty: retty,
    })
}
/// Parse a subprogram specification. This covers the initial part of a
/// subprogram declaration, body, instantiation, or interface declaration. See
/// IEEE 1076-2008 sections 4.2 and 6.5.4. Note that not all combinations of
/// keywords and qualifiers that this parser accepts are actually valid.
///
/// ```text
/// subprog_spec :=
///   ["pure"|"impure"] "procedure"|"function" primary_name
///   ["generic" paren_expr]
///   ["generic" "map" paren_expr]
///   [["parameter"] paren_expr]
///   ["return" name]
/// ```
Parse a subprogram specification. This covers the initial part of a
subprogram declaration, body, instantiation, or interface declaration.


Parse a subprogram specification . This covers the initial part of a subprogram declaration body instantiation or interface declaration .
pub fn parse_subprog_spec<P: Parser>(p: &mut P) -> ReportedResult<ast::SubprogSpec> {
    let mut span = p.peek(0).span;
    // Parse the optional purity qualifier.
    let purity = match p.peek(0).value {
        Keyword(Kw::Pure) => {
            p.bump();
            Some(ast::SubprogPurity::Pure)
        }
        Keyword(Kw::Impure) => {
            p.bump();
            Some(ast::SubprogPurity::Impure)
        }
        _ => None,
    };
    // Parse the subprogram kind.
    let pk = p.peek(0);
    let kind = match pk.value {
        Keyword(Kw::Procedure) => {
            p.bump();
            ast::SubprogKind::Proc
        }
        Keyword(Kw::Function) => {
            p.bump();
            ast::SubprogKind::Func
        }
        wrong => {
            p.emit(
                DiagBuilder2::error(format!(
                    "Expected `procedure` or `function`, found {} instead",
                    wrong
                ))
                .span(span)
                .add_note("see IEEE 1076-2008 section 4.2"),
            );
            return Err(Reported);
        }
    };
    // Parse the name.
    let name = match try_primary_name(p) {
        Some(n) => n,
        None => {
            let pk = p.peek(0);
            p.emit(
                DiagBuilder2::error(format!(
                    "Expected subprogram name, found {} instead",
                    pk.value
                ))
                .span(pk.span)
                .add_note("A subprogram name is either an identifier or an operator symbol")
                .add_note("see IEEE 1076-2008 section 4.2"),
            );
            return Err(Reported);
        }
    };
    // Parse the optional generic clause.
    let gc = if p.peek(0).value == Keyword(Kw::Generic) && p.peek(1).value != Keyword(Kw::Map) {
        p.bump();
        Some(flanked(p, Paren, |p| {
            Ok(separated_nonempty(
                p,
                Semicolon,
                CloseDelim(Paren),
                "generic interface declaration",
                |p| parse_intf_decl(p, Some(ast::IntfObjKind::Const)),
            )?)
        })?)
    } else {
        None
    };
    // Parse the optional generic map aspect.
    let gm = try_map_aspect(p, Kw::Generic)?;
    // Parse the optional parameter keyword and list.
    let params = if accept(p, Keyword(Kw::Parameter)) || p.peek(0).value == OpenDelim(Paren) {
        Some(flanked(p, Paren, |p| {
            Ok(separated_nonempty(
                p,
                Semicolon,
                CloseDelim(Paren),
                "parameter interface declaration",
                |p| parse_intf_decl(p, Some(ast::IntfObjKind::Var)),
            )?)
        })?)
    } else {
        None
    };
    // Parse the optional return type.
    let retty = if accept(p, Keyword(Kw::Return)) {
        Some(parse_name(p)?)
    } else {
        None
    };
    span.expand(p.last_span());
    Ok(ast::SubprogSpec {
        span: span,
        name: name,
        kind: kind,
        purity: purity,
        generic_clause: gc,
        generic_map: gm,
        params: params,
        retty: retty,
    })
}
pub fn parse_subprog_spec < P : Parser > ( p : & mut P ) -> ReportedResult < ast :: SubprogSpec > { let mut span = p . peek ( 0 ) . span ; // Parse the optional purity qualifier. let purity = match p . peek ( 0 ) . value { Keyword ( Kw :: Pure ) => { p . bump ( ) ; Some ( ast :: SubprogPurity :: Pure ) } Keyword ( Kw :: Impure ) => { p . bump ( ) ; Some ( ast :: SubprogPurity :: Impure ) } _ => None , } ; // Parse the subprogram kind. let pk = p . peek ( 0 ) ; let kind = match pk . value { Keyword ( Kw :: Procedure ) => { p . bump ( ) ; ast :: SubprogKind :: Proc } Keyword ( Kw :: Function ) => { p . bump ( ) ; ast :: SubprogKind :: Func } wrong => { p . emit ( DiagBuilder2 :: error ( format ! ( " " wrong ) ) . span ( span ) . add_note ( " " ) , ) ; return Err ( Reported ) ; } } ; // Parse the name. let name = match try_primary_name ( p ) { Some ( n ) => n , None => { let pk = p . peek ( 0 ) ; p . emit ( DiagBuilder2 :: error ( format ! ( " " pk value ) ) . span ( pk . span ) . add_note ( " " ) . add_note ( " " ) , ) ; return Err ( Reported ) ; } } ; // Parse the optional generic clause. let gc = if p . peek ( 0 ) . value == Keyword ( Kw :: Generic ) && p . peek ( 1 ) . value != Keyword ( Kw :: Map ) { p . bump ( ) ; Some ( flanked ( p , Paren , | p | { Ok ( separated_nonempty ( p , Semicolon , CloseDelim ( Paren ) , " " , | p | parse_intf_decl ( p , Some ( ast :: IntfObjKind :: Const ) ) , ) ? ) } ) ? ) } else { None } ; // Parse the optional generic map aspect. let gm = try_map_aspect ( p , Kw :: Generic ) ? ; // Parse the optional parameter keyword and list. let params = if accept ( p , Keyword ( Kw :: Parameter ) ) || p . peek ( 0 ) . value == OpenDelim ( Paren ) { Some ( flanked ( p , Paren , | p | { Ok ( separated_nonempty ( p , Semicolon , CloseDelim ( Paren ) , " " , | p | parse_intf_decl ( p , Some ( ast :: IntfObjKind :: Var ) ) , ) ? ) } ) ? ) } else { None } ; // Parse the optional return type. let retty = if accept ( p , Keyword ( Kw :: Return ) ) { Some ( parse_name ( p ) ? ) } else { None } ; span . expand ( p . last_span ( ) ) ; Ok ( ast :: SubprogSpec { span : span , name : name , kind : kind , purity : purity , generic_clause : gc , generic_map : gm , params : params , retty : retty , } ) }
Parse a subprogram specification.
Parse a subprogram specification .
p
&mut P
p
&mut P