
                 Reference Analysis Traversal Specification
                          Revised - 21 March 1994



INTRODUCTION

This document specifies an Asis traversal which locates and classifies
all name references within an Ada compilation unit.

A name reference is An_Expression element of the following kinds:

   * A_Simple_Name
   * An_Operator_Symbol
   * A_Character_Literal
   * An_Enumeration_Literal

Each of these elements has a corresponding An_Entity_Name_Definition
element that can be reached using Name_Definition.  The
Enclosing_Element of the An_Entity_Name_Definition is the
A_Declaration or A_Statement element that declares the entity.

The traversal walks the Asis element hierarchy of a comp unit in
top-to-bottom, left-to-right order.   A reference category is
an inherited attribute that is carried along during the traversal.
The reference category is set (and possibly reset) as the traversal 
enters different contexts.  When a name reference is encountered, it 
is categorized with the value of the current reference category.

In addition to the reference category, there are two additional
inherited attributes:

   1) Type Mark Context
   2) Data Access Context

The Type Mark Context is a category indicating the context of an Ada
type_mark (3.3.2).  Because type_mark appears frequently in the Ada
syntax, the Type Mark Context provides additional information about
how type_marks are used.  Whenever a reference of category Type_Mark
is recorded by the traversal, the current value of the Type Mark
Context is associated with the reference.

The Data Access Context is a category indicating the context of
references to objects.  Whenever a reference of categories Read,
Update, or Read_And_Update is recorded, the current value of the Data
Access Context is associated with the reference.

A companion document describes the reference categories and also the
Type Mark Context and Data Access Context categories used by this traversal.

TRAVERSAL

The remainder of the document describes the Asis traversal.  The
traversal is organized by LRM section.  For each section, the Ada
syntax productions appearing in that section are listed, followed by
the corresponding "productions" from ASIS/LRM Crossreference document.

The ASIS productions have been annotated to specify :

  1) Which children of a given element should be traversed, and
  2) The values to be assigned to the inherited attributes, i.e., the
     reference category and the two context categories.

ASIS (@_Kinds) productions are annotated with '+' and '-' symbols.
'+' indicates elements of that kind should be traversed, while '-'
indicates kinds that can be skipped.  '+' annotations include the LRM
section number of the element's definition.

Each ASIS (Element) production is copied verbatim from the
Crossreference document.  Traversal of an element's subelement is
indicated by the inclusion of the appropriate (Query) or (Query,List)
production following the (Element) production.  For example, consider
the element production for A_Variable_Declaration:


   A_Variable_Declaration ::= (Element)
      Names : Object_Declaration_Definition [ := Initial_Value ] ;

   Object_Declaration_Definition ::= (Query)
      A_Type_Definition

      * Traverse A_Type_Definition (3.3.1)
      * Type Mark Context := Object_Declaration

   Initial_Value ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Object_Declaration

A_Variable_Declaration element has three subelements.  The presence of
Object_Declaration_Definition and Initial_Value query productions here
indicates that those subelements should be traversed.  The absence of
the query for Names indicates that subelement should NOT be traversed.

Along with each query production is a directive (beginning with '*')
that specifies how to traverse the subelement.  If no change is to be
made to the inherited attributes, then the directive is "Traverse", e.g., 

      * Traverse A_Type_Definition (3.3.1)

The directive includes the LRM section of subelement's definition.

"Ref_Cat" directives generally are used when the kind of the
subelement is An_Expression.  These directives specify a new value for
the reference category.  In the example above, the reference category
becomes 'Read'.

Settings for the Type Mark Context and Data_Access_Context are also
specified via directives, as the example shows.

-------------------------------------------------------------------------------

2.8

pragma ::= PRAGMA identifier 
               [ ( argument_association { , argument_association } ) ] ;

argument_association ::= 
   [ argument_identifier => ] name
 | [ argument_identifier => ] expression

   A_Pragma ::= (Element)
      PRAGMA Name [ ( { Argument_Associations } ) ] ;

   Argument_Associations ::= (Query, List 0..N)
      An_Argument_Association

   An_Argument_Association ::= (Element)
      [ Formal_Parameter => ] Actual_Parameter

   Actual_Parameter ::= (Query)
      An_Expression

      * Ref_Cat := Pragma

NOTE: not all pragma arguments will have a corresponding Name_Definition.

3.1

   A_Declaration ::= (Declaration_Kinds)
      A_Component_Declaration (3.7) +
    | A_Constant_Declaration (3.2.1) +
    | A_Deferred_Constant_Declaration (7.4) +
    | A_Discriminant_Specification (3.7.1) +
    | An_Entry_Declaration (9.5) +
    | An_Enumeration_Literal_Specification -
    | An_Exception_Declaration -
    | An_Exception_Rename_Declaration (8.5) +
    | A_Full_Type_Declaration (3.3.1) +
    | A_Function_Body_Declaration (6.3) +
    | A_Function_Body_Stub (10.2) +
    | A_Function_Declaration (6.1) +
    | A_Function_Instantiation (12.3) +
    | A_Function_Rename_Declaration  (8.5) +
    | A_Generic_Formal_Function_Declaration (12.1) +
    | A_Generic_Formal_Object_Declaration (12.1) +
    | A_Generic_Formal_Private_Type_Declaration (12.1) +
    | A_Generic_Formal_Procedure_Declaration (12.1) +
    | A_Generic_Formal_Type_Declaration (12.1) +
    | A_Generic_Function_Declaration (12.1) +
    | A_Generic_Package_Declaration (12.1) +
    | A_Generic_Procedure_Declaration (12.1) +
    | An_Incomplete_Type_Declaration (3.8.1) +
    | An_Integer_Number_Declaration (3.2.2) +
    | A_Loop_Parameter_Specification (5.5) +
    | An_Object_Rename_Declaration (8.5) +
    | A_Package_Body_Declaration (7.1) +
    | A_Package_Body_Stub -
    | A_Package_Declaration (7.1) +
    | A_Package_Instantiation (12.3) +
    | A_Package_Rename_Declaration (8.5) +
    | A_Parameter_Specification (6.1) +
    | A_Private_Type_Declaration (7.4) +
    | A_Procedure_Body_Declaration (6.3) +
    | A_Procedure_Body_Stub (10.2) +
    | A_Procedure_Declaration (6.1) +
    | A_Procedure_Instantiation (12.3) +
    | A_Procedure_Rename_Declaration (8.5) +
    | A_Real_Number_Declaration (3.2.2) +
    | A_Subtype_Declaration (3.3.2) +
    | A_Task_Body_Declaration (9.1) +
    | A_Task_Body_Stub -
    | A_Task_Declaration (9.1) +
    | A_Task_Type_Declaration (9.1) +
    | A_Variable_Declaration (3.2.1) +
    
3.2.1

object_declaration ::=
   identifier_list : [ CONSTANT ] subtype_indication [ := expression ] ;
 | identifier_list : [ CONSTANT ] constrained_array_definition
                                                     [ := expression ] ;

   A_Variable_Declaration ::= (Element)
      Names : Object_Declaration_Definition [ := Initial_Value ] ;

   A_Constant_Declaration ::= (Element)
      Names : Object_Declaration_Definition [ := Initial_Value ] ;

   Object_Declaration_Definition ::= (Query)
      A_Type_Definition

      * Traverse A_Type_Definition (3.3.1)
      * Type Mark Context := Object_Declaration

   Initial_Value ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Object_Declaration

3.2.2

number_declaration ::= 
   identifier_list : CONSTANT := expression;

   An_Integer_Number_Declaration ::= (Element)
      Names : constant := Initial_Value ;

   An_Real_Number_Declaration ::= (Element)
      Names : constant := Initial_Value ;

   Initial_Value ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Number_Declaration

3.3.1

full_type_declaration ::=
   TYPE identifier [ discriminant_part ] IS type_definition ;

   A_Full_Type_Declaration ::= (Element)
      TYPE Names [ ( Discriminants ) ] IS Type_Declaration_Definition ;

   Discriminants ::= (Query, List 0..N)
      A_Discriminant_Specification

      * Traverse A_Discriminant_Specification (3.7.1)

   Type_Declaration_Definition ::= (Query)
      A_Type_Definition

      * Traverse A_Type_Definition (3.3.1)

   A_Type_Definition ::=
      An_Access_Type_Definition (3.8) +
    | An_Array_Type_Definition (3.6) +
    | A_Derived_Type_Definition (3.4) +
    | An_Enumeration_Type_Definition -
    | A_Fixed_Type_Definition (3.5.9) +
    | A_Float_Type_Definition (3.5.7) +
    | A_Generic_Access_Type_Definition (12.1) +
    | A_Generic_Array_Type_Definition (12.1) +
    | A_Generic_Discrete_Subtype_Definition -
    | A_Generic_Fixed_Subtype_Definition -
    | A_Generic_Float_Subtype_Definition -
    | A_Generic_Integer_Subtype_Definition -
    | A_Generic_Limited_Private_Type_Definition -
    | A_Generic_Private_Type_Definition -
    | An_Integer_Type_Definition (3.5.4) +
    | A_Limited_Private_Type_Definition -
    | A_Private_Type_Definition -
    | A_Record_Type_Definition (3.7) +
    | A_Subtype_Definition (3.3.2) +
    | A_Task_Type_Definition (9.1) +

3.3.2

subtype_declaration ::=
   SUBTYPE identifier IS subtype_indication ;

subtype_indication ::= type_mark [ constraint ]

type_mark ::= name

   A_Subtype_Declaration ::= (Element)
      SUBTYPE Names IS Type_Declaration_Definition ;

   Type_Declaration_Definition ::= (Query)
      A_Type_Definition 

      * Traverse A_Type_Definition (3.3.1)
      * Type Mark Context := Subtype_Declaration

   A_Subtype_Definition ::= (Element)
      Subtype_Definition_Subtype_Indication

   Subtype_Definition_Subtype_Indication ::= (Query)
      A_Subtype_Indication

   A_Subtype_Indication ::= (Element)
      Type_Mark [ Subtype_Constraint ]

   Type_Mark ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark   

   Subtype_Constraint ::= (Query)
      A_Constraint

      * Traverse A_Constraint (3.3.2)

   A_Constraint ::= (Constraint_Kinds)
      A_Discriminant_Constraint (3.7.2) +
    | A_Fixed_Point_Constraint (3.5.9) +
    | A_Floating_Point_Constraint (3.5.7) +
    | An_Index_Constraint (3.6) +
    | A_Range_Attribute (3.5) +
    | A_Simple_Range (3.5) +

3.4

derived_type_definition ::= NEW subtype_indication

   A_Derived_Type_Definition ::= (Element)
      NEW Parent_Subtype

   Parent_Subtype ::= (Query)
      A_Subtype_Indication

      * Traverse A_Subtype_Indication (3.3.2)
      * Type Mark Context := Derived_Type_Definition


3.5

range_constraint ::= RANGE range

range ::= attribute
        | simple_expression .. simple_expression

   A_Range_Attribute ::= (Element)
      RANGE Range_Attribute

   Range_Attribute ::= (Query)
      An_Expression

      * Traverse An_Expression (4.4)

   A_Simple_Range ::= (Element)
      RANGE Lower_Bound .. Upper_Bound

   Lower_Bound ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Range
   
   Upper_Bound ::= (Query)
      An_Expression
   
      * Ref_Cat := Read
      * Data Access Context := Range

3.5.4

integer_type_definition ::= range_constraint

   An_Integer_Type_Definition ::= (Element)
      Integer_Constraint

   Integer_Constraint ::= (Query)
      A_Constraint

      * Traverse A_Constraint (3.3.2)

3.5.7

floating_point_constraint ::=
   floating_accuracy_definition [ range_constraint ]

floating_accuracy_definition := DIGITS simple_expression

   A_Float_Type_Definition ::= (Element)
      Real_Type_Constraint

   Real_Type_Constraint ::= (Query)
      A_Constraint

      * Traverse A_Constraint (3.3.2)

   A_Floating_Point_Constraint ::= (Element)
      DIGITS Floating_Accuracy_Definition 
                [ Floating_Point_Range_Constraint ]

   Floating_Accuracy_Definition ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Floating_Accuracy_Definition

   Floating_Point_Range_Constraint ::= (Query)
      A_Constraint

      * Traverse A_Constraint (3.3.2)

3.5.9

fixed_point_constraint ::=
   fixed_accuracy_definition [ range_constraint ]

fixed_accuracy_definition ::= DELTA simple_expression

   A_Fixed_Type_Definition ::= (Element)
      Real_Type_Constraint

   Real_Type_Constraint ::= (Query)
      A_Constraint

      * Traverse A_Constraint

   A_Fixed_Point_Constraint ::= (Element)
      DELTA Fixed_Accuracy_Definition [ Fixed_Point_Range_Constraint ]

   Fixed_Accuracy_Definition ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Fixed_Accuracy_Definition

   Fixed_Point_Range_Constraint ::= (Query)
      A_Constraint

      * Traverse A_Constraint

3.6

array_type_definition ::= 
   unconstrained_array_definition
 | constrained_array_definition

unconstrained_array_definition ::=
   ARRAY ( index_subtype_definition { , index_subtype_definition } ) OF
      subtype_indication

constrained_array_definition ::=
   ARRAY index_constraint OF subtype_indication

index_subtype_definition ::= type_mark RANGE <>

   An_Array_Type_Definition ::= (Element)
      ARRAY Index_Constraint OF Component_Subtype_Indication
    | ARRAY ( Index_Subtype_Definitions ) OF Component_Subtype_Indication ;
   
   Index_Constraint ::= (Query)
      A_Constraint

      * Traverse A_Constraint (3.3.2)

   Index_Subtype_Definitions ::= (Query, 1..N)
      An_Expression

      * Ref_Cat := Type_Mark   
      * Type Mark Context := Index_Subtype_Definition

   Component_Subtype_Indication ::= (Query)
      A_Subtype_Indication

      * Traverse A_Subtype_Indication (3.3.2)
      * Type Mark Context := Array_Definition

3.6.1

index_constraint ::= ( discrete_range {, discrete_range } )

discrete_range ::= subtype_indication | range

   An_Index_Constraint ::= (Element)
      ( Discrete_Ranges )

      * Traverse Discrete_Range with Type Mark Context := Index_Constraint

   Discrete_Ranges ::= (Query, List 1..N)
      A_Discrete_Range

   A_Discrete_Range ::= (Discrete_Range_Kinds)
      A_Discrete_Subtype_Indication
    | A_Range_Attribute
    | A_Simple_Range

   A_Discrete_Subtype_Indication ::= (Element)
      Type_Mark [ Subtype_Constraint ]
   
   Type_Mark ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark   

   Subtype_Constraint ::= (Query)
      A_Constraint

      * Traverse A_Constraint (3.3.2)

   Range_Attribute ::= (Query)
      An_Expression

      * Traverse An_Expression (4.4)

   A_Simple_Range ::= (Element)
      RANGE Lower_Bound .. Upper_Bound

   Lower_Bound ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Range
   
   Upper_Bound ::= (Query)
      An_Expression
   
      * Ref_Cat := Read
      * Data Access Context := Range

3.7

record_type_definition ::=
   RECORD 
      component_list
   END RECORD

component_list ::=
   component_declaration { component_declaration }
 | { component_declaration } variant_part
 | NULL ;

component_declaration ::=
   identifier_list : component_subtype_definition [ := expression ] ;

component_subtype_definition ::= subtype_indication

   A_Record_Type_Definition ::= (Element)
      RECORD Record_Components END RECORD

   Record_Components ::= (Query, List 1..N)
      A_Record_Component

   A_Record_Component ::= (Component_Kinds)
      A_Component_Declaration +
    | A_Null_Component -
    | A_Pragma (2.8) +
    | A_Variant_Part (3.7.3) +

   A_Component_Declaration ::= (Element)
      Names : Object_Declaration_Definition [ := Initial_Value ]

   Object_Declaration_Definition ::= (Query)
      A_Type_Definition

      * Traverse A_Type_Definition (3.3.1)
      * Type Mark Context := Component_Subtype_Definition

   Initial_Value ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Component_Declaration

3.7.1

discriminant_specification ::= 
   identifier_list : type_mark [ := expression ]

   A_Discriminant_Specification ::= (Element)
      Names : Type_Mark [ := Initial_Value ]

   Type_Mark ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark   
      * Type Mark Context := Discriminant_Specification

   Initial_Value ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Discriminant_Specification

3.7.2

discriminant_constraint ::=
   ( discriminant_association {, discriminant_association } )

discriminant_association ::=
   [ simple_name { | simple_name } => ] expression

   A_Discriminant_Constraint ::= (Element)
      ( Discriminant_Associations )

   Discriminant_Associations ::= (Query, List 1..N)
      A_Discriminant_Association

   A_Discriminant_Association ::= (Element)
      [ Discriminant_Simple_Names => ] Discriminant_Expression

   Discriminant_Simple_Names ::= (Query, List 0..N)
      A_Simple_Name

      * Ref_Cat := Discriminant_Association

   Discriminant_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Discriminant_Association

3.7.3

variant_part ::=
   CASE simple_name Is
      variant
      { variant }
   END CASE;

variant ::=
   WHEN choice { | choice } =>
      component_list

choice := simple_expression
        | discrete_range
        | OTHERS
        | simple_name

   A_Variant_Part := (Element)
      CASE Corresponding_Discriminant_Simple_Name IS { Variants } END CASE ;
      
   Corresponding_Discriminant_Simple_Name ::= (Query)
      A_Simple_Name

      * Ref_Cat := Variant_Part_Discriminant

   Variants ::= (Query, List 1..N)
      A_Variant
      
   A_Variant ::= (Element)
      WHEN Variant_Choices =>
         Variant_Components

   Variant_Choices ::= (Query, List 1..N)
      A_Choice

   Variant_Components ::= (Query)
      A_Record_Component

      * Traverse A_Record_Component (3.7)  

   A_Choice ::= (Choice_Kinds)
      A_Discrete_Range +
    | An_Expression +
    | An_Others_Choice -
    | A_Simple_Name +
    | An_Exception_Name +

   Choice_Simple_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Choice

   Choice_Discrete_Range ::= (Query)
      A_Discrete_Range

      * Traverse A_Discrete_Range (3.6.1)
      * Type Mark Context := Choice

   Choice_Name ::= (Query)
      A_Simple_Name

      * Ref_Cat := Read
      * Data Access Context := Choice

3.8

access_type_definition ::= ACCESS subtype_indication

   An_Access_Type_Definition ::= (Element)
      ACCESS Access_To

   Access_To ::= (Query)
      A_Subtype_Indication

      * Traverse A_Subtype_Indication (3.3.2)
      * Type Mark Context := Access_Type_Definition

3.8.1

incomplete_type_declaration ::=
   TYPE identifier [ discriminant_part ] ;

   An_Incomplete_Type_Declaration ::= (Element)
      TYPE Names [ ( Discriminants ) ] ;

   Discriminants ::= (Query, List 0..N)
      A_Discriminant_Specification

      * Traverse A_Discriminant_Specification (3.7.1)

4.1

name ::= simple_name
       | character_literal
       | operator_symbol
       | indexed_component  (see 4.1.1)
       | slice              (see 4.1.2)
       | selected_component (see 4.1.3)
       | attribute          (see 4.1.4)

simple_name ::= identifier

prefix ::= name 
         | function_call

   For element kinds:

      A_Simple_Name
      An_Operator_Symbol
      A_Character_Literal
      An_Enumeration_Literal

   Record a reference of the current Ref_Cat to the referenced
   Entity_Name_Definition.

   If the Ref_Cat = Type_Mark, then associate the current Type Mark
   Context with the reference.

   If the Ref_Cat = Read, Update, or Read_And_Update, then associate
   the current Data Access context with the reference.

   NOTE: There is one case where the Ref_Cat must be changed.  If
   the name is A_Character_Literal or An_Enumeration_Literal AND
   Ref_Cat = Read, record a Ref_Cat of 'Evaluate' on the reference.
   (This occurs because enumeration literals can occur in an
   expression; we consider objects occurring in an expression to be
   read and enumeration literals evaluated.)


4.1.1 

indexed_component ::= prefix ( expression {,expression} )
                           
   An_Indexed_Component ::= (Element)
      Prefix ( Index_Expressions )

   Index_Expressions ::= (Query, List 1..N)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Indexed_Component

   Prefix processing:

      if the indexed component denotes the component of an array then
         if the type kind of the prefix is an access type then
            Record a reference of the current Ref_Cat to the entity name
              corresponding to Ground_Type (access type).
            Traverse prefix with Ref_Cat := Read.
         else
            Scan prefix with current Ref_Cat.
         end if;
      else
         Scan prefix with current Ref_Cat.
      end if;

Notes:
 
A collection is always associated with a base type.  Furthermore, for
a derived type of an access type, the derived type shares the same
collection with the parent type (3.4(9)); hence, the ASIS function
Ground_Type is used so that we will always show a reference to the ultimate
parent type.  

The referenced type may be a generic access type definition.
We view such types as having their own collections.

4.1.2 

slice ::= prefix ( discrete_range )

   A_Slice ::= (Element)
      Prefix ( Slice_Range )

   Slice_Range ::= (Query)
      A_Discrete_Range

      * Traverse A_Discrete_Range (3.6.1)
      * Type Mark Context := Slice

   Prefix processing:

      if the type kind of the prefix is an access type then
         Record a reference of the current Ref_Cat to the entity name
           corresponding to Ground_Type (access type).
         Traverse prefix with Ref_Cat := Read.
      else
         Scan prefix with current Ref_Cat.
      end if;

4.1.3

selected_component ::= prefix.selector

selector ::= simple_name
           | character_literal
           | operator_symbol
           | ALL

   A_Selected_Component ::= (Element)
      Prefix . Selector

   Selector ::= (Query)
      An_Expression

   Prefix and Selector processing:

      case Selection_Kind( A_Selected_Component ) is
         when A_Discriminant
            | A_Record_Component =>
            if the type kind of the prefix is an access type then
               Record a reference of the current Ref_Cat to the entity name
                 corresponding to Ground_Type (access type).
               Traverse prefix with Ref_Cat := Read.
            else
               Traverse prefix with current Ref_Cat.
            end if;
            Traverse Selector with Ref_Cat := Selected_Component;
         when A_Task_Entry =>
            if the type kind of the prefix is an access type then
               Record a reference of kind Task_Entry_Selection to the 
                  entity name corresponding to Ground_Type (access type).
               Traverse prefix with Ref_Cat := Read.
            else
               Traverse prefix with Ref_Cat := Task_Entry_Selection.
            end if;
            Traverse Selector with current Ref_Cat
         when An_Access_Object =>
            (The type kind of the prefix is known to be an access type.)
            Record a reference of the current Ref_Cat to the 
               entity name corresponding to Ground_Type (access type).
            Traverse prefix with Ref_Cat := Read.
         when An_Expanded_Name =>
            Traverse Prefix with Ref_Cat := Expanded_Name
            Traverse Selector with current Ref_Cat
      end case;

4.1.4

attribute ::= prefix ' attribute_designator

attribute_designator ::= simple_name [ ( expression ) ]

   An_Attribute ::= (Element)
      Prefix ' Attribute_Designator_Name [ (
                                  Attribute_Designator_Argument ) ]

   Attribute_Designator_Name ::= (Query)
      A_Simple_Name

      * No traversal

   Attribute_Designator_Argument ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Attribute_Argument

   Prefix processing:

      if the type kind of the prefix is an access type then
         Record a reference of kind Attribute to the entity name
           corresponding to Ground_Type (access type).
         Traverse prefix with Ref_Cat := Read.
      else
         Traverse prefix with Ref_Cat := Attribute.
      end if;


Note that certain attributes appear in ASIS as function calls!

4.2

Ignore literals

4.3 

aggregate ::= ( component_association , { component_association } )

component_association ::= 
   [ choice { | choice } => ] expression

   An_Aggregate ::= (Element)
      ( Components )

   Components ::= (Query, List 1..N)
      A_Component_Association
   
   A_Component_Association ::= (Element)
      [ Component_Choices => ] Component_Expression

   Component_Choices ::= (Query, List 0..N)
      A_Choice

   A_Choice ::= (Choice_Kinds)
      A_Discrete_Range +
    | An_Expression +
    | An_Others_Choice -
    | A_Simple_Name +
    | An_Exception_Name -

   Choice_Simple_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Expression Context := Choice

   Choice_Discrete_Range ::= (Query)
      A_Discrete_Range

      * Traverse A_Discrete_Range (3.6.1)
      * Type Mark Context := Choice

   Choice_Name ::= (Query)
      A_Simple_Name

      * if record aggregate then
           Ref_Cat := Component_Association
        else -- array aggregate
           Ref_Cat := Read
           Data Access Context := Choice
        end if

?????
Can we distinguish between record and array aggregates?
?????
   
   Component_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Component_Association

4.4

expression ::=
   relation { AND relation } | relation { AND THEN relation }
 | relation { OR relation }  | relation { OR ELSE relation }
 | relation { XOR relation }

relation ::=
   simple_expression [ relational_operator simple_expression ]
 | simple_expression [ NOT ] IN range
 | simple_expression [ NOT ] IN type_mark

simple_expression ::=
   [ unary_adding_operator } term { binary_adding_operator term }

term ::= factor { multiplying_operator factor }

factor ::= 
   primary [ ** primary ] 
 | ABS primary 
 | NOT primary

primary ::= 
   numeric_literal
 | NULL
 | aggregate
 | string_literal
 | name
 | allocator
 | function_call
 | type_conversion
 | qualified_expression
 | ( expression )
     

   An_Expression ::= (Expression_Kinds)
      An_Aggregate (4.3) +
    | An_Allocation_From_Qualified_Expression (4.8) +
    | An_Allocation_From_Subtype (4.8) +
    | An_Attribute (4.1.4) +
    | A_Character_Literal (4.1) +
    | An_Enumeration_Literal (4.1) +
    | A_Function_Call (6.4) +
    | An_Indexed_Component (4.1.1) +
    | An_Integer_Literal -
    | A_Null_Literal -
    | An_Operator_Symbol (4.1) +
    | A_Simple_Name (4.1) +
    | A_Parenthesized_Expression (4.4) +
    | A_Qualified_Expression (4.7) +
    | A_Real_Literal -
    | A_Selected_Component (4.1.3) +
    | A_Slice (4.1.2) +
    | A_Special_Operation (4.4) +
    | A_String_Literal -
    | A_Type_Conversion (4.6) +

   A_Parenthesized_Expression ::= (Element)
      ( Expression_Parenthesized )

   Expression_Parenthesized ::= (Query)
      An_Expression

      * Traverse with the current Ref_Cat and Context

   A_Special_Operation ::= (Special_Operation_Kinds)
      An_And_Then
    | An_In_Range
    | An_In_Type
    | A_Not_In_Range
    | A_Not_In_Type
    | An_Or_Else

   An_And_Then ::= (Element)
      Special_Operation_Left_Hand_Side AND THEN
         Short_Circuit_Operation_Right_Hand_Side

   An_Or_Else ::= (Element)
      Special_Operation_Left_Hand_Side OR ELSE
         Short_Circuit_Operation_Right_Hand_Side

   An_In_Range ::= (Element)
      Special_Operation_Left_Hand_Side IN
         In_Range_Operation_Right_Hand_Side

   A_Not_In_Range ::= (Element)
      Special_Operation_Left_Hand_Side NOT IN
         In_Range_Operation_Right_Hand_Side

   An_In_Type ::= (Element)
      Special_Operation_Left_Hand_Side IN
         In_Type_Operation_Right_Hand_Side

   A_Not_In_Type ::= (Element)
      Special_Operation_Left_Hand_Side NOT IN
         In_Type_Operation_Right_Hand_Side

   Special_Operation_Left_Hand_Side ::= (Query)
      An_Expression

      * Traverse with current Ref_Cat and Data Access Context

   In_Range_Operation_Right_Hand_Side ::= (Query)
      A_Constraint

      * Traverse A_Constraint (3.3.2)

   In_Type_Operation_Right_Hand_Side ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type Mark Context := Membership_Test

   Short_Circuit_Operation_Right_Hand_Side ::= (Query)
      An_Expression

      * Traverse with current Ref_Cat and Data Access Context

4.6

type_conversion ::= type_mark ( expression )

   A_Type_Conversion ::= (Element)
      Type_Mark ( Converted_Or_Qualified_Expression )

   Type_Mark ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type_Mark Context := Type_Conversion

   Converted_Or_Qualified_Expression ::= (Query)
      An_Expression

      * Traverse with the current Ref_Cat and Data Access Context

4.7

qualified_expression ::= 
   type_mark ' ( expression )
   type_mark ' aggregate

   A_Qualified_Expression ::= (Element)
      Type_Mark ' ( Converted_Or_Qualified_Expression )

   Type_Mark ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type_Mark Context := Qualified_Expression

   Converted_Or_Qualified_Expression ::= (Query)
      An_Expression

      * Traverse with the current Ref_Cat and Data Access Context

4.8

allocator ::= 
   NEW subtype_indication | NEW qualified_expression

   An_Allocation_From_Subtype ::= (Element)
      NEW Allocation_Type

   Allocation_Type ::= (Query)
      A_Subtype_Indication

      * Traverse A_Subtype_Indication (3.3.2)
      * Type Mark Context := Allocator

   An_Allocation_From_Qualified_Expression ::= (Element)
      NEW Qualified_Object_Expression

   Qualified_Object_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Allocator

5.1

   A_Statement ::= (Statement_Kinds)
      An_Abort_Statement (9.10) +
    | An_Accept_Statement (9.5) +
    | An_Assignment_Statment (5.2) +
    | A_Block_Statement (5.6) +
    | A_Case_Statement (5.4) +
    | A_Code_Statement (13.8) +
    | A_Conditional_Entry_Call_Statement (9.7.2) +
    | A_Delay_Statement (9.6) +
    | An_Entry_Call_Statement (9.5) +
    | An_Exit_Statement (5.7) +
    | A_Goto_Statement (5.9) +
    | An_If_Statement (5.3) +
    | A_Loop_Statement (5.5) +
    | A_Null_Statement -
    | A_Pragma (2.8 ) +
    | A_Procedure_Call_Statement (6.4) +
    | A_Raise_Statement (11.3) +
    | A_Return_Statement (5.8) +
    | A_Selective_Wait_Statement (9.7.1) +
    | A_Timed_Entry_Call_Statement (9.7.3) +

5.2

assignment_statement ::= name := expression;

   Object_Assigned_To ::= (Query)
     An_Expression

      * Ref_Cat := Update
      * Data Access Context := Assignment_Statement_Name

   Assignment_Expression ::= (Query)
     An_Expression

      * Ref_Cat := Read
      * Data Access Context := Assignment_Statement_Expression

5.3

if_statement ::= IF condition THEN
                    sequence_of_statements
               { ELSIF condition THEN
                    sequence_of_statements }
               [ ELSE
                    sequence_of_statements ]
                 END IF

condition ::= expression

   An_If_Statement ::= (Element)
    { << Label_Names >> }
      IF { If_Statement_Arms } END IF ;

   If_Statement_Arms ::= (Query, List 1..N)
      An_If_Statement_Arm

   An_If_Statement_Arm ::= (If_Statement_Arm_Kinds)
      An_Else_Arm +
    | An_Elsif_Arm +
    | An_If_Arm +

   An_If_Arm ::= (Element)
      IF Condition_Expression THEN { Arm_Statements }

   An_Elsif_Arm ::= (Element)
      ELSIF Condition_Expression THEN { Arm_Statements }

   An_Else_Arm ::= (Element)
      ELSE { Arm_Statements }

   Condition_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := If_Condition

   Arm_Statements ::= (Query, List 1..N)
      A_Statement

      * Traverse A_Statement (5.1)

5.4

case_statement ::= CASE expression IS
                      case_statement_alternative
                      { case_statement_alternative }
                   END CASE ;

case_statement_alternative ::= WHEN choice { | choice } =>
                                  sequence_of_statements

   A_Case_Statement ::= (Element)
    { << Label_Names >> }
      CASE Case_Expression IS Case_Statement_Alternatives END CASE ;

   Case_Expression ::= (Query)
      An_Expression

      Ref_Cat := Read
      Data_Access_Context := Case_Statement

   Case_Statement_Alternatives ::= (Query, List 1..N)
      A_Case_Statement_Alternative

   A_Case_Statement_Alternative ::= (Element)
      WHEN Case_Statement_Alternative_Choices =>
         Case_Statement_Alternative_Statements

   Case_Statement_Alternative_Choices ::= (Query, List 1..N)
      A_Choice

      * Traverse A_Choice (3.7.3)

   Case_Statement_Alternative_Statements ::= (Query, List 1..N)
      A_Statement

      * Traverse A_Statement (5.1)

5.5

loop_statement ::= 
 [ loop_simple_name : ]
   [ iteration_scheme ] LOOP
      sequence_of_statements
   END LOOP [ loop_simple_name ] ;

iteration_scheme ::=
   WHILE condition
 | FOR loop_parameter_specification

loop_parameter_specification ::=
   identifier IN [ REVERSE ] discrete_range

   A_Loop_Statement ::= (Loop_Kinds)
      A_For_Loop +
    | A_Simple_Loop +
    | A_While_Loop +

   A_While_Loop ::= (Element)
     { << Label_Names >> }
     [ Loop_Simple_Name : ]
       WHILE While_Condition LOOP { Loop_Statements } END LOOP ;

   While_Condition ::= (Query)
      An_Expression 

      * Ref_Cat := Read
      * Data Access Context := While_Loop_Condition

   A_For_Loop ::= (Element)
    { << Label_Names >> }
    [ Loop_Simple_Name : ]
      FOR For_Loop_Parameter_Specification LOOP { Loop_Statements }
                                           END LOOP ;
   
   For_Loop_Parameter_Specification ::= (Query)
      A_Loop_Parameter_Specification

   A_Loop_Parameter_Specification ::= (Element)
      Names IN [REVERSE] Loop_Parameter_Range
      
   Loop_Parameter_Range ::= (Query)
      A_Discrete_Range

      * Traverse A_Discrete_Range (3.6.1)
      * Type Mark Context := Loop_Parameter_Specification

   A_Simple_Loop ::= (Element)
    { << Label_Names >> }
    [ Loop_Simple_Name : ]
      LOOP { Loop_Statements } END LOOP ;

   Loop_Statements ::= (Query, List 1..N)
      A_Statement

      * Traverse A_Statement

5.6

block_statement ::= 
 [ block_simple_name : ]
 [ DECLARE
      declarative_part ]
   BEGIN
      sequence_of_statements
 [ EXCEPTION
      exception_handler
    { exception_handler } ]
   END [ block_simple_name ] ;

   A_Block_Statement ::= (Element)
      { << Label_Names >> }
      [ Block_Simple_Name : ]
      [ DECLARE
           Declarative_Items ]
        BEGIN
           Block_Body_Statements
      [ EXCEPTION
           Block_Exception_Handlers ]
        END ;

   Declarative_Items ::= (Query, List 0..N)
      Element

      * Traverse A_Declaration, (3.1) 
                 A_Pragma, (2.8 )
                 A_Representation_Clause, (13.1)
                 A_Use_Clause (8.4) 

   Block_Body_Statements ::= (Query, List 1..N)
      A_Statement

      * Traverse A_Statement (5.1)

   Block_Exception_Handlers ::= (Query, List 0..N)
      An_Exception_Handler

      * Traverse An_Exception_Handler (11.2)

5.7

exit_statement ::= EXIT [ loop_name ] [ WHEN condition ] ;

   An_Exit_Statement ::= (Element)
    { << Label_Names >> }
      EXIT [ Exit_Loop_Name ] [ WHEN Exit_Condition ]

   Exit_Loop_Name ::= (Query)
      An_Expression
   
      * Ref_Cat := Exit_Loop_Name

   Exit_Condition ::= (Query)

      * Ref_Cat := Read
      * Data Access Context := Exit_Condition
   
5.8

return_Statement ::= RETURN [ expression ];

   A_Return_Statement ::= (Element)
    { << Label_Names >> }
      RETURN [ Return_Expression ] ;

   Return_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Return_Statement
   
5.9

goto_statement ::= GOTO label_name ;

   A_Goto_Statement ::= (Element)
      { << Label_names >> }
        GOTO Goto_Label

   Goto_Label ::= (Query)
      An_Expression

      * Ref_Cat := Goto_Target

6.1

subprogram_declaration ::= subprogram_specification ;

subprogram_specification ::
   PROCEDURE identifier [ formal_part ]
 | FUNCTION designator [ formal_part ] RETURN type_mark

designator ::= identifier | operator_symbol

formal_part ::=
   ( parameter_specification { ; parameter_specification } )

parameter_specification ::=
   identifier_list : mode type_mark [ := expression ]

mode ::= [ IN ] | IN OUT | OUT

   A_Procedure_Declaration ::= (Element)
      PROCEDURE Names [ ( Parameters ) ]

   A_Function_Declaration ::= (Element)
      FUNCTION Names [ ( Parameters ) ] RETURN Return_Type ;

   Parameters ::= (Query, List 0..N)
      A_Parameter_Specification

   A_Parameter_Specification ::= (Parameter_Mode_Kinds)
      A_Default_In_Mode +
    | An_In_Mode +
    | An_In_Out_Mode +
    | An_Out_Mode +

   Return_Type ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type_Mark Context := Function_Declaration

   A_Default_In_Mode ::= (Element)
      Names : Type_Mark [ := Initial_Value ]

   An_In_Mode ::= (Element)
      Names : IN Type_Mark [ := Initial_Value ]

   An_Out_Mode ::= (Element)
      Names : OUT Type_Mark

   An_In_Out_Mode ::= (Element)
      Names : IN OUT Type_Mark

   Initial_Value ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Parameter_Specification

   Type_Mark ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type Mark Context := Parameter_Specification

6.3

subprogram_body ::=
   subprogram_specification IS
      [ declarative_part ]
   BEGIN
      sequence_of_statements
 [ EXCEPTION
      exception_handler
    { exception_handler } ]
   END [ designator ] ;

   A_Procedure_Body_Declaration ::= (Element)
      PROCEDURE Names [ ( Parameters ) ] IS
         Subprogram_Body_Block
      END Names ;

   A_Function_Body_Declaration ::= (Element)
      FUNCTION Names { ( Parameters ) ] RETURN Return_Type IS
         Subprogram_Body_Block

   Parameters ::= (Query, List 0..N)
      A_Parameter_Specification

      * Traverse A_Parameter_Specification (6.1)

   Return_Type ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type Mark Context := Function_Body

   Subprogram_Body_Block ::= (Query) 
      A_Block_Statement

      * Traverse A_Block_Statement (5.6)

6.4

procedure_call_statement ::= name [ actual_parameter_part ]

actual_parameter_part ::= ( parameter_association {, parameter_association } )

parameter_association ::= [ formal_parameter => ] actual_parameter

formal_parameter ::= simple_name

actual_parameter ::= expression
                   | name
                   | type_mark ( name )

   A_Procedure_Call_Statement ::= (Element)
    { << Label_Names >> }
      Called_Name [ ( Call_Parameters ) ] ;

   Called_Name ::= (Query)
     An_Expression

      * Ref_Cat := Procedure_Call

   Call_Parameters ::= (Query, List 0..N)
      A_Parameter_Association

   A_Parameter_Association := (Element)
      [ Formal_Parameter => ] Actual_Parameter

   Formal_Parameter ::= (Query)
      A_Simple_Name

      * Ref_Cat( A_Parameter_Specification ) := Parameter_Association

   Actual_Parameter ::= (Query)
      An_Expression

      * Ref_Cat := Read, Read_And_Update, or Update
      * Data Access Context := Actual_Parameter

	Category depends on whether the mode of the corresponding
	formal is IN, IN OUT, or OUT, respectively.

	NOTE: In making these classifications, we assume that the
	called procedure reads IN and IN OUT parameters and updates
	IN OUT and OUT parameters.

function_call ::= name [ actual_parameter_part ]

   A_Function_Call ::= (Element)
      Prefix [ ( Function_Call_Parameters ) ]

   Prefix ::= (Query)
      An_Expression

      * Ref_Cat := Function_Call

   Function_Call_Parameters ::= (Query, List 0..N)
      A_Parameter_Association

      * Traverse A_Parameter_Association

7.1

package_declaration ::= package_specification;

package_specification ::=
   PACKAGE identifier IS
      { basic_declarative_item }
 [ PRIVATE
      { basic_declarative_item } ]
   END [ simple_name ] ;
      
package_body ::=
   PACKAGE BODY simple_name IS
      { declarative_part }
 [ BEGIN
      sequence_of_statements
 [ EXCEPTION
      exception_handler
    { exception_handler } ]]
   END [ simple_name ] ;

   A_Package_Declaration ::= (Element)
      PACKAGE Names IS
         { Visible_Part_Declarative_Items }
    [ PRIVATE
         { Private_Part_Declarative_Items } ]
      END ;

   Visible_Part_Declarative_Items ::= (Query, List 0..N)
      Element

      * Traverse A_Declaration, (3.1) 
                 A_Pragma, (2.8 )
                 A_Representation_Clause, (13.1)
                 A_Use_Clause (8.4) 

   Private_Part_Declarative_Items ::= (Query, List 0..N)
      Element

      * Traverse A_Declaration, (3.1) 
                 A_Pragma, (2.8 )
                 A_Representation_Clause, (13.1)
                 A_Use_Clause (8.4) 

   A_Package_Body_Declaration ::= (Element)
      PACKAGE BODY Names IS Package_Body_Block ;

   Package_Body_Block ::= (Query)
      A_Block_Statement

      * Traverse A_Block_Statement (5.6)

7.4

private_type_declaration ::=
   TYPE identifier [ discriminant_part ] IS [ LIMITED ] PRIVATE ;

deferred_constant_declaration ::=
   identifier_list : CONSTANT type_mark ;

   A_Private_Type_Declaration ::= (Element)
      TYPE Names [ ( Discriminants ) ] IS Type_Declaration_Definition ;

   Discriminants ::= (Query, List 0..N)
      A_Discriminant_Specification

      * Traverse A_Discriminant_Specification (3.7.1)

   Type_Declaration_Definition ::= (Query)
      A_Type_Definition

      * Traverse A_Type_Definition (3.3.1)

   A_Deferred_Constant_Declaration ::= (Element)
      Names : CONSTANT Type_Mark ;

   Type_Mark ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type Mark Context := Deferred_Constant_Declaration

8.4

use_clause ::= USE name { , name }

   A_Use_Clause ::= (Element)
      USE { Named_Packages } ;

   Named_Packages ::= (Query, List 1..N)
      An_Expression

      * Ref_Cat := Use_Clause

8.5

renaming_declaration ::=
   identifier : type_mark RENAMES name ;
 | identifier : EXCEPTION RENAMES name ;
 | PACKAGE identifier RENAMES name ;
 | subprogram_specification RENAMES name ;

   An_Object_Rename_Declaration ::= (Element)
      Names : Type_Mark RENAMES Renamed_Entity ;

   Type_Mark ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type Mark Context := Renaming_Declaration

   Renamed_Entity ::= (Query)
      An_Expression

      * Ref_Cat := Rename
   
   An_Exception_Rename_Declaration ::= (Element)
      Names : EXCEPTION RENAMES Renamed_Entity ;

   Renamed_Entity ::= (Query)
      An_Expression

      * Ref_Cat := Rename
   
   A_Package_Rename_Declaration ::= (Element)
      PACKAGE Names RENAMES Renamed_Entity ;

   Renamed_Entity ::= (Query)
      An_Expression

      * Ref_Cat := Rename
   
   A_Procedure_Rename_Declaration ::= (Element)
      PROCEDURE Names [ ( Parameters ) ] RENAMES Renamed_Entity ;

   Parameters ::= (Query, List 0..N)
      A_Parameter_Specification

      * Traverse A_Parameter_Specification (6.1)

   Renamed_Entity ::= (Query)
      An_Expression

      * Ref_Cat := Rename

   A_Function_Rename_Declaration ::= (Element)
      FUNCTION Names [ ( Parameters ) ] RETURN Return_Type RENAMES
         Renamed_Entity ;

   Parameters ::= (Query, List 0..N)
      A_Parameter_Specification

      * Traverse A_Parameter_Specification (6.1)

   Return_Type ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type Mark Context := Function_Rename

   Renamed_Entity ::= (Query)
      An_Expression

        * Ref_Cat := Rename
 	  (Note: attribute functions, which can be renamed, appear as
	  A_Function_Declarations in ASIS.)

9.1

task_declaration ::= task_specification

task_specification ::=
   TASK [ TYPE ] identifier [ IS
      { entry_declaration }
      { representation_clause }
   END [ simple_name ]] ;

task_body ::=
   TASK BODY simple_name IS
      [ declarative_part ]
   BEGIN
      sequence_of_statements
 [ EXCEPTION
      exception_handler
    { exception_handler } ]
   END [ simple_name ] ;

   A_Task_Type_Declaration ::= ( Element )
      TASK TYPE Names IS Type_Declaration_Definition END ;

   Type_Declaration_Definition ::= (Query)
      A_Type_Definition

      * Traverse A_Type_Definition (3.3.1)

   A_Task_Type_Definition ::= (Element)
      { Task_Type_Declarative_Items }

   Task_Type_Declarative_Items ::= (Query, List 0..N)
      Element

      * Traverse A_Declaration, (3.1) 
                 A_Pragma, (2.8 )
                 A_Representation_Clause, (13.1)

   A_Task_Declaration ::= (Element)
      TASK Names IS { Task_Declaration_Declarative_Items } END ;

   Task_Declaration_Declarative_Items ::= (Query, List 0..N)
      Element

      * Traverse A_Declaration, (3.1) 
                 A_Pragma, (2.8 )
                 A_Representation_Clause, (13.1)

   A_Task_Body_Declaration ::= (Element)
      TASK BODY Names IS Task_Body_Block END ;

   Task_Body_Block ::= (Query)
      A_Block_Statement

      * Traverse A_Block_Statement (5.6)

9.5

entry_declaration ::=
   ENTRY identifier [ ( discrete_range ) ] [ formal_part ] ;

   An_Entry_Declaration ::= (Element)
      ENTRY Names [ ( Family_Index ) ] [ ( Parameters ) ] ;

   Family_Index ::= (Query)
      A_Discrete_Range

      * Traverse A_Discrete_Range (3.6.1)
      * Type Mark Context := Entry_Declaration

   Parameters ::= (Query, List 0..N)
      A_Parameter_Specification

      * Traverse A_Parameter_Specification (6.1)

entry_call_statement ::= name [ actual_parameter_part ]

   An_Entry_Call_Statement ::= (Element)
    { << Label_Names >> }
      Called_Name [ Family_Index { Call_Parameters } ]

   Called_Name ::= (Query)
      An_Expression

      * Ref_Cat := Entry_Call

NOTE: Don't use function Family_Index for an entry call.  Called_Name
returns an indexed_component if a family index appears in the call.

   Call_Parameters ::= (Query, List 0..N)
      A_Parameter_Association

      * Traverse A_Parameter_Association (6.4), using entry
        specification of called entry to determine formal parameter modes.

accept_statement ::= (Element)
   ACCEPT simple_name [ ( entry_index ) ] [ formal_part ] [ DO
      sequence_of_statements
   END [ simple_name ]] ;

entry_index := expression

   An_Accept_Statement ::= (Element)
    { << Label_Names >> }
      ACCEPT Accept_Entry_Simple_Name [ ( Family_Index ) ] [ (
                                         Accept_Parameters ) ] [ DO
         Accept_Body_Statements
      END ] ;

   Accept_Entry_Simple_Name ::= (Query)
      A_Simple_Name

      * Ref_Cat := Accept_Statement 

   Family_Index ::= (Query)         (Here it is correct to use Family_Index)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Entry_Index

   Accept_Parameters ::= (Query, List 0..N)
      A_Parameter_Specification

      * Traverse A_Parameter_Specification (6.1)

   Accept_Body_Statements ::= (Query, List 0..N)
      A_Statement

      * Traverse A_Statement (5.1)

9.6

delay_statement ::= DELAY simple_expression;

   A_Delay_Statement ::= (Element)
    { << Label_Names >> }
      DELAY Delay_Expression 

   Delay_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Delay_Statement

9.7

select_statement ::= selective_wait
                   | conditional_entry_call
                   | timed_entry_call

9.7.1

selective_wait ::= 
   SELECT
      select_alternative
 { OR
      select_alternative }
 [ ELSE
      sequence_of_statements ]
   END SELECT ;
 
select_alternative ::=
 [ WHEN condition => ]
      selective_wait_alternative

selective_wait_alternative ::=
   accept_alternative
 | delay_alternative
 | terminate_alternative

accept_alternative ::=
   accept_statement [ sequence_of_statements ]

delay_alternative ::= 
   delay_statement [ sequence_of_statements ]

terminate_alternative ::= TERMINATE ;

   A_Selective_Wait_Statement ::= (Element)
    { << Label_Names >> }
      SELECT { Select_Statement_Arms } END SELECT ;

   Select_Statement_Arms ::= (Query, List 1..N)
      A_Select_Statement_Arm

   A_Select_Statement_Arm ::= (Select_Statement_Arm_Kinds)
      A_Conditional_Entry_Call_Else_Arm (9.7.2) +
    | A_Conditional_Entry_Call_Select_Arm (9.7.2) +
    | A_Selective_Wait_Else_Arm +
    | A_Selective_Wait_Or_Arm +
    | A_Selective_Wait_Select_Arm +
    | A_Timed_Entry_Call_Or_Arm (9.7.3) +
    | A_Timed_Entry_Call_Else_Arm (9.7.3) +

   A_Selective_Wait_Select_Arm ::= (Element)
      Arm_Select_Alternative

   A_Selective_Wait_Or_Arm ::= (Element)
      Arm_Select_Alternative

   A_Selective_Wait_Else_Arm ::= (Element)
      { Else_Statements }

   Else_Statements ::= (Query, List 1..N)
      A_Statement

      * Traverse A_Statement (5.1)

   Arm_Select_Alternative ::= (Query)
      A_Select_Alternative

   A_Select_Alternative ::= (Select_Alternative_Kinds)
      An_Accept_Alternative +
    | A_Delay_Alternative +
    | A_Terminate_Alternative +

   An_Accept_Alternative ::= (Element)
    [ WHEN Guard => ]
       { Select_Alternative_Statements }

   A_Delay_Alternative ::= (Element)
    [ WHEN Guard => ]
       { Select_Alternative_Statements }

   A_Terminate_Alternative ::= (Element)
    [ WHEN Guard => ]
         TERMINATE ;

   Guard ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Select_Alternative

   Select_Alternative_Statements ::= (Query, List 1..N)
      A_Statement
      
      * Traverse A_Statement (5.1)

9.7.2

conditional_entry_call ::=
   SELECT
      entry_call_statement
    [ sequence_of_statements ]
   ELSE
      sequence_of_statements
   END SELECT ;

   A_Conditional_Entry_Call_Statement ::= (Element)
    { << Label_Names >> }
      SELECT Select_Statement_Arms END SELECT ;

   Select_Statement_Arms ::= (Query, List 1..N)
      A_Select_Statement_Arm

      * Traverse A_Select_Statement_Arm (9.7.1)

   A_Conditional_Entry_Call_Select_Arm ::= (Element)
      { Entry_Call_Statements }

   Entry_Call_Statements ::= (Query, List 1..N)
      A_Statement

      * Traverse A_Statement (5.1)

   A_Conditional_Entry_Call_Else_Arm ::= (Element)
      { Else_Statements }

   Else_Statements ::= (Query, List 1..N)
      A_Statement

      * Traverse A_Statement (5.1)

9.7.3

timed_entry_call ::=
   SELECT
      entry_call_statement
    [ sequence_of_statements ]
   OR
      delay_alternative
   END SELECT ;

   A_Timed_Entry_Call_Statement ::= (Element)
    { << Label_Names >> }
      SELECT Select_Statement_Arms END SELECT ;

   Select_Statement_Arms ::= (Query, List 1..N)
      A_Select_Statement_Arm

      * Traverse A_Select_Statement_Arm (9.7.1)

   A_Timed_Entry_Call_Select_Arm ::= (Element)
      { Entry_Call_Statements }

   Entry_Call_Statements ::= (Query, List 1..N)
      A_Statement

      * Traverse A_Statement (5.1)

   A_Timed_Entry_Call_Or_Arm ::= (Element)
      { Timed_Entry_Call_Or_Statements }

   Timed_Entry_Call_Or_Statements ::= (Query, List 1..N)
      A_Statement

      * Traverse A_Statement (5.1)

9.10

abort_statement ::= ABORT name {, name}

   An_Abort_Statement ::= (Element)
    { << Label_Names >> }
      ABORT { Aborted_Tasks } ;

   Aborted_Tasks ::= (Query, List 1..N)
      An_Expression

      * Ref_Cat := Abort

10.1

compilation_unit ::=
   context_clause library_unit
 | context_clause secondary_unit

   Unit_Declaration ::= (Query : Comp Unit - Element Gateway)
      A_Declaration

      * Traverse A_Declaration (3.1)

10.1.1

context_clause ::= { with_clause { use_clause }}

with_clause ::= WITH simple_name { , simple_name } ;

   Context_Clause_Elements ::= (Query, List 0..N : Comp Unit - Element Gateway)
      Element

      * Traverse A_With_Clause
		 A_Use_(Context)_Clause
		 A_Pragma (2.8)

   A_With_Clause ::= (Element)
      WITH { Referenced_Units } ;

   Referenced_Units ::= (Query)
      A_Simple_Name

      * Ref_Cat := With_Clause

   A_Use_(Context)_Clause ::= (Element)
      USE { Referenced_Units } ;

   Referenced_Units ::= (Query)
      A_Simple_Name

      * Ref_Cat := Use_Context_Clause

10.2

body_stub ::=
   subprogram_specification IS SEPARATE ;
 | PACKAGE BODY simple_name IS SEPARATE ;
 | TASK BODY simple_name IS SEPARATE ;

   A_Procedure_Body_Stub ::= (Element)
      PROCEDURE Names [ ( Parameters ) ] IS SEPARATE ;

   A_Function_Body_Stub ::= (Element)
      FUNCTION Names [ ( Parameters ) ] RETURN Return_Type IS_SEPARATE ;

   Parameters ::= (Query, List 0..N)
      A_Parameter_Specification

      * Traverse A_Parameter_Specification (6.1)

   Return_Type ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type Mark Context := Function_Stub

11.2

exception_handler ::=
   WHEN exception_choice { | exception_choice } =>
      sequence_of_statements

exception_choice ::= name | others

   An_Exception_Handler ::= (Element)
      WHEN Exception_Choices =>
         Handler_Statements

   Exception_Choices ::= (Query, List 1..N)
      A_Choice

   A_Choice ::= (Choice_Kinds)
      A_Discrete_Range -
    | An_Expression +
    | An_Others_Choice -
    | A_Simple_Name -
    | An_Exception_Name +

   Choice_Simple_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Handle

   Choice_Name ::= (Query)
      A_Simple_Name

      * Ref_Cat := Handle

   Handler_Statements ::= (Query, List 1..N)
      A_Statement

      * Traverse A_Statement (5.1)
   
11.3

raise_statement ::= RAISE [ name ] ;

   A_Raise_Statement ::= (Element)
    { << Label_Names >> }
      RAISE [ Raised_Exception ] 

   Raised_Exception ::= (Query)
      An_Expression

      * Ref_Cat := Raise    

12.1

generic_declaration ::= generic_specification ;

generic_specification ::= 
   generic_formal_part subprogram_specification
 | generic_formal_part package_specification

generic_formal_part ::= GENERIC { generic_parameter_declaration }

generic_parameter_declaration ::=
   identifier_list : [ IN [ OUT ]] type_mark [ := expression ] ;
 | TYPE identifier IS generic_type_definition ;
 | private_type_declaration
 | WITH subprogram_specification [ IS name ] ;
 | WITH subprogram_specification [ IS <> ] ;

generic_type_definition ::= 
   (<>) | RANGE <> | DIGITS <> | DELTA <>
 | array_type_definition
 | access_type_definition

   A_Generic_Procedure_Declaration ::= (Element)
      GENERIC
      { Generic_Formal_Parameters }
      PROCEDURE Names [ ( Parameters ) ] ;

   A_Generic_Function_Declaration ::= (Element)
      GENERIC
      { Generic_Formal_Parameters }
      FUNCTION Names [ ( Parameters ) ] RETURN Return_Type ;
   
   Parameters ::= (Query, List 0..N)
      A_Parameter_Specification

      * Traverse A_Parameter_Specification (6.1)

   Return_Type ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type Mark Context := Generic_Function

   A_Generic_Package_Delcaration ::= (Element)
      GENERIC
      { Generic_Formal_Parameters }
      PACKAGE Names IS
      { Visible_Part_Declarative_Items }
    [ PRIVATE
      { Private_Part_Declarative_Items } ]
      END ;      

   Visible_Part_Declarative_Items ::= (Query, List 0..N)
      Element

      * Traverse A_Declaration, (3.1) 
                 A_Pragma, (2.8 )
                 A_Representation_Clause, (13.1)
                 A_Use_Clause (8.4) 

   Private_Part_Declarative_Items ::= (Query, List 0..N)
      Element

      * Traverse A_Declaration, (3.1) 
                 A_Pragma, (2.8 )
                 A_Representation_Clause, (13.1)
                 A_Use_Clause (8.4) 

   Generic_Formal_Parameters ::= (Query, List 0..N)
      A_Declaration

      * Traverse A_Declaration (3.1)

   A_Generic_Formal_Object_Declaration ::= (Parameter_Mode_Kinds)
      A_Default_In_Mode +
    | An_In_Mode +
    | An_In_Out_Mode +

   A_Default_In_Mode ::= (Element)
      Names : Type_Mark [ := Initial_Value ]

   An_In_Mode ::= (Element)
      Names : IN Type_Mark [ := Initial_Value ]

   An_In_Out_Mode ::= (Element)
      Names : IN OUT Type_Mark

   Initial_Value ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Generic_Parameter_Declaration

   Type_Mark ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type Mark Context := Generic_Parameter_Declaration

   A_Generic_Formal_Type_Declaration ::= (Element)
      TYPE Names IS Type_Declaration_Definition ;

   A_Generic_Formal_Private_Type_Declaration ::= (Element)
      TYPE Names [ ( Discriminants ) ] IS Type_Declaration_Definition ;

   Discriminants ::= (Query, List 0..N)
      A_Discriminant_Specification

      * Traverse A_Discriminant_Specification (3.7.1)

   Type_Declaration_Definition ::= (Query)
      A_Type_Definition

      * Traverse A_Type_Definition (3.3.1)

   A_Generic_Formal_Procedure_Declaration ::= (Element)
      WITH PROCEDURE Names [ ( Parameters ) ] [ IS <> ] ;
    | WITH PROCEDURE Names [ ( Parameters ) ] 
        [ IS Generic_Formal_Subprogram_Default ] ;

   A_Generic_Formal_Function_Declaration ::= (Element)
      WITH FUNCTION Names [ ( Parameters ) ] RETURN Return_Type [ IS <> ] ;
    | WITH FUNCTION Names [ ( Parameters ) ] RETURN Return_Type
        [ IS Generic_Formal_Subprogram_Default ] ;

   Parameters ::= (Query, List 0..N)
      A_Parameter_Specification

      * Traverse A_Parameter_Specification (6.1)

   Return_Type ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type Mark Context := Generic_Formal_Function

   Generic_Formal_Subprogram_Default ::= (Query)
      An_Expression

      * Ref_Cat := Generic_Formal_Subprogram_Default

   A_Generic_Access_Type_Definition ::= (Element)
      An_Access_Type_Definition

      * Traverse An_Access_Type_Definition (3.8)

   A_Generic_Array_Type_Definition ::= (Element)
      An_Array_Type_Definition

      * Traverse An_Array_Type_Definition (3.6)

12.3

generic_instantiation ::=
   PACKAGE identifier IS
      NEW name [ generic_actual_part ] ;
 | PROCEDURE identifier IS
      NEW name [ generic_actual_part ] ;
 | FUNCTION designator IS
      NEW name [ generic_actual_part ] ;

generic_actual_part ::= 
   ( generic_assocation { , generic_association } )

generic_association ::=
 [ generic_formal_parameter => ] generic_actual_parameter

generic_formal_parameter ::=
   simple_name | operator_symbol

generic_actual_parameter ::= 
   expression
 | name
 | type_mark

   A_Package_Instantiation ::= (Element)
      PACKAGE Names IS NEW Generic_Unit_Name [ ( Generic_Parameters ) ] ;

   A_Procedure_Instantiation ::= (Element)
      PROCEDURE Names IS NEW Generic_Unit_Name [ ( Generic_Parameters ) ] ;

   A_Function_Instantiation ::= (Element)
      FUNCTION Names IS NEW Generic_Unit_Name [ ( Generic_Parameters ) ] ;

   Generic_Unit_Name ::= (Query)
      An_Expression 

      * Ref_Cat := Instantiation

   Generic_Parameters ::= (Query, List 0..N)
      A_Parameter_Association

*** NOTE: We handle parameter associations in instantiations
          differently than we do in subprogram calls!

   A_Parameter_Association := (Element)
      [ Formal_Parameter => ] Actual_Parameter

   Formal_Parameter ::= (Query)
      A_Simple_Name

      * Ref_Cat := Generic_Association

   Actual_Parameter ::= (Query)
      An_Expression

      * If the formal parameter is an object of mode IN, then the
        actual is an expression that will be evaluated; hence:

           Ref_Cat := Read
           Data Access Context := Generic_Actual_Parameter

      * For any other kind of formal parameter, the name given as
        the actual is classified as Generic_Actual_Parameter.

           Ref_Cat := Generic_Actual_Parameter

13.1

representation_clause ::=
   type_representation_clause
 | address_clause

type_representation_clause ::=
   length_clause
 | enumeration_representation_clause
 | record_representation_clause

   A_Representation_Clause ::=(Representation_Clause_Kinds)
      An_Address_Clause (13.5) +
    | An_Enumeration_Representation_Clause (13.3) +
    | A_Length_Clause (13.2) +
    | A_Record_Representation_Clause (13.4) +

13.2

length_clause ::= FOR attribute USE simple_expression ;

   A_Length_Clause ::= (Element)
      FOR Length_Clause_Attribute USE Length_Clause_Simple_Expression ;

   Length_Clause_Attribute ::= (Query)
      An_Attribute

   An_Attribute ::= (Element)
      Prefix ' Attribute_Designator_Name

      * Traverse Prefix with Ref_Cat := Length_Clause

NOTE: Attribute prefix is traversed locally so that the type name in
the prefix will not be categorized as Attribute.

   Length_Clause_Simple_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Length_Clause

13.3

enumeration_representation_clause ::=
   FOR simple_name USE aggregate ;

   An_Enumeration_Represtation_Clause ::= (Element)
      FOR Enumeration_Representation_Clause_Type_Simple_Name
         USE Enumeration_Representation_Clause_Aggregate ;

   Enumeration_Representation_Clause_Type_Simple_Name ::= (Query)
      A_Simple_Name

      * Ref_Cat := Enumeration_Rep_Clause

   Enumeration_Representation_Clause_Aggregate ::= (Query)
      An_Aggregate

NOTE: Aggregate is traversed locally so that the choices in the
aggregate are categorized as Component_Association.

   An_Aggregate ::= (Element)
      ( Components )

   Components ::= (Query, List 1..N)
      A_Component_Association
   
   A_Component_Association ::= (Element)
      [ Component_Choices => ] Component_Expression

   Component_Choices ::= (Query, List 0..N)
      A_Choice

   A_Choice ::= (Choice_Kinds)
      A_Discrete_Range -
    | An_Expression +
    | An_Others_Choice -
    | A_Simple_Name +
    | An_Exception_Name -

   Choice_Simple_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Component_Association

   Choice_Name ::= (Query)
      A_Simple_Name

      * Ref_Cat := Component_Association
   
   Component_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Component_Association

13.4

record_representation_clause ::=
   FOR simple_name USE
      RECORD [ alignment_clause ]
         { component_clause }
      END RECORD ;

alignment_clause ::= AT MOD simple_expression ;

component_clause ::=
   name AT simple_expression RANGE range ;

   A_Record_Representation_Clause ::= (Element)
      FOR Record_Representation_Clause_Type_Simple_Name USE
         RECORD [ AT MOD
                  Record_Representation_Clause_Alignment_Clause_Expression ; }
          { Component_Clauses }
         END RECORD ;

   Record_Representation_Clause_Type_Simple_Name ::= (Query)
      A_Simple_Name

      * Ref_Cat := Record_Rep_Clause

   Record_Representation_Clause_Alignment_Clause_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Alignment_Clause

   Component_Clauses ::= (Query, List 0..N)
      A_Component_Clause

   A_Component_Clause ::= (Element)
      Component_Clause_Name AT Component_Clause_Relative_Address
         RANGE Component_Clause_Range ;

   Component_Clause_Name ::= (Query)
      A_Simple_Name

      * Ref_Cat := Component_Clause

   Component_Clause_Relative_Address ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Component_Clause

   Component_Clause_Range ::= (Query)
      A_Discrete_Range

      * Traverse A_Discrete_Range (3.6.1)

13.5 

address_clause ::=
   FOR simple_name USE AT simple_expression ;

   An_Address_Clause ::= (Element)
      FOR Address_Clause_Simple_Name USE AT Address_Clause_Simple_Expression ;

   Address_Clause_Simple_Name ::= (Query)
      A_Simple_Name

      * Ref_Cat := Address_Clause

   Address_Clause_Simple_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Address_Clause

13.8

code_statement ::= type_mark ' record_aggregrate

   A_Code_Statement ::= (Element)
    { << Label_Names >> }
      Qualified_Expression

NOTE : the qualified expression and the aggregate it contains are both
traverse locally.

   Qualified_Expression ::= (Query)
      An_Qualified_Expression

   A_Qualified_Expression ::= (Element)
      Type_Mark ' ( Converted_Or_Qualified_Expression )

   Type_Mark ::= (Query)
      An_Expression

      * Ref_Cat := Type_Mark
      * Type_Mark Context := Code_Statement

   Converted_Or_Qualified_Expression ::= (Query)
      An_Aggregate

   An_Aggregate ::= (Element)
      ( Components )

   Components ::= (Query, List 1..N)
      A_Component_Association
   
   A_Component_Association ::= (Element)
      [ Component_Choices => ] Component_Expression

   Component_Choices ::= (Query, List 0..N)
      A_Choice

   A_Choice ::= (Choice_Kinds)
      A_Discrete_Range -
    | An_Expression +
    | An_Others_Choice -
    | A_Simple_Name +
    | An_Exception_Name -

   Choice_Simple_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Component_Association

   Choice_Name ::= (Query)
      A_Simple_Name

      * Ref_Cat := Component_Association
   
   Component_Expression ::= (Query)
      An_Expression

      * Ref_Cat := Read
      * Data Access Context := Component_Association

