(*-----------------------------------------------------------------------------
(* (C) Altran Praxis Limited
(*-----------------------------------------------------------------------------
(*
(* The SPARK toolset is free software; you can redistribute it and/or modify it
(* under terms of the GNU General Public License as published by the Free
(* Software Foundation; either version 3, or (at your option) any later
(* version. The SPARK toolset is distributed in the hope that it will be
(* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
(* Public License for more details. You should have received a copy of the GNU
(* General Public License distributed with the SPARK toolset; see file
(* COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
(* the license.
(*
(*=============================================================================


------------------------------------------------------------------------------*)
(*  SPARK.LLA

  Purpose:
    This file contains an LALR (1) grammar for the SPARK Language.  It is used
    by the SPARK parser-generator SparkLALR to automatically construct a parser
    which creates a syntax tree as a SPARK text is read.
    The automatically generated parser requires a lexical analyser to partition
    a SPARK text into a sequence of terminal symbols.  For the Examiner SparkLex
    serves this purpose.

    The grammar file has the following conventions:
    1.  Comments are multi-line and are designated as in Pascal.  See the
        comment block containing this documentation.
        Comments cannot be nested, hence the comment delimiters cannot be
        given explicitly here.

    2.  The grammar file has two main sections
        a.  The terminal definitions designated by the string "&TERM" followed
            by a list of terminal symbols separated by commas.
        b.  The grammar rules designated by the string "&GRAM" followed by a
            list of production rules separated by semicolons. The rules define
            the non-terminal symbols of the grammar.

    3.  A grammar rule is defined in BNF format with ":" symbol replacing "::=".

    4.  Comments containing section numbers refer to the SPARK language
        definition: SPARK 95 - The SPADE Ada 95 Kernel (including RAVENSPARK).

  Clients:
    SparkLALR generates the parser SPParser which is then used by the
    Examiner MainLoop.

  Use:
    The SPARK.LLA grammar file is an input to the SPARK parser-generator
    SparkLALR which is to used create a parser for SPARK texts, SPParser.
    A SPARK package defining all the terminal and non-terminal symbols of the
    grammar as an enumerated type is required for SPParser and the lexical
    analyser SparkLex.
    In the Examiner the package SP_Symbols contains the declaration of the
    enumerated type SPSymbol.
    The symbols enumerated in the declaration of SPSymbol must be consistent
    with those appearing in the grammar file.

  Extension:
    SPARK.LLA should be updated with extreme caution as the parser generated
    from it creates a syntax tree which is directly used by the Examiner for
    its analysis.  If the structure of the grammar and therefore the syntax
    tree is changed the Examiner will not behave correctly until it is
    updated to recognise the changed syntax tree structure.

    It is possible to extend the grammar without affecting the existing Examiner
    functionality providing the basic structure of the productions remains
    unchanged.  The following sorts of extensions are possible with caution
    1.  Add a new terminal symbol (update SP_Symbols correspondingly).

    2.  Add a new non-terminal symbol via a new production (update SP_Symbols
        correspondingly).

    3.  Add one or more further options to an existing production.

    Any extra productions or extended productions must maintain the constraints
    placed on an LALR(1) grammar.
------------------------------------------------------------------------------*)
&TERM

(* Spark Terminal Symbols (From Lexical Analyser) *)

predefined_FDL_identifier,

(* 2.2 *)
ampersand,
apostrophe,
left_paren,
right_paren,
multiply,
plus,
comma,
minus,
point,
divide,
colon,
semicolon,
less_than,
equals,
greater_than,
vertical_bar,

tilde,
percent,

arrow,
double_dot,
double_star,
becomes,
not_equal,
greater_or_equal,
less_or_equal,
left_label_paren,
right_label_paren,
box,

(* FDL operators *)
implies,
is_equivalent_to,
square_open,
square_close,

(* 2.3 *)
identifier,

(* 2.4 *)
(* numeric_literal, *)
integer_number,
real_number,
based_integer,
based_real,

(* 2.5 *)
character_literal,

(* 2.6 *)
string_literal,

(* 2.7 *)
comment,

(* 2.9 *)
RWabort,
RWabs,
RWabstract,
RWaccept,
RWaccess,
RWaliased,
RWall,
RWand,
RWandthen,
RWany,
RWarray,
RWassert,
RWassume,
RWat,

RWbegin,
RWbody,

RWcase,
RWcheck,
RWconstant,

RWdeclare,
RWdelay,
RWdelta,
RWderives,
RWdigits,
RWdo,

RWelse,
RWelsif,
RWend,
RWentry,
RWexception,
RWexit,

RWfrom,
RWfor,
RWforall,
RWforsome,
RWfunction,

RWgeneric,
RWglobal,
RWgoto,

RWhide,

RWif,
RWin,
RWinherit,
RWinitializes,
RWis,
RWinterface,

RWlimited,
RWloop,

RWmain_program,
RWmod,

RWnew,
RWnot,
RWnotin,
RWnull,

RWof,
RWor,
RWorelse,
RWothers,
RWout,
RWoverriding,
RWown,

RWpackage,
RWpost,
RWpragma,
RWpre,
RWprivate,
RWprocedure,
RWprotected,

RWraise,
RWrange,
RWrecord,
RWrem,
RWrenames,
RWrequeue,
RWreturn,
RWreverse,

RWselect,
RWseparate,
RWsome
RWsubtype,
RWsynchronized,

RWtagged,
RWtask,
RWterminate,
RWthen,
RWtype,

RWuntil,
RWuse,

RWwhen,
RWwhile,
RWwith,

RWxor,

(* 2.11 *)
annotation_end,
annotation_start,
annotation_continuation,
proof_context,
hide_directive,

(* 4.1.4 *)
attribute_ident,

(* Illegal Tokens *)
illegal_id,
illegal_number,
illegal_token,
illegal_comment,
unterminated_string,

&GRAM
(* SPARK Production Rules *)

(* 10.1 *)
(* b *)
compilation_unit :
     context_clause library_unit
   |                library_unit
   | context_clause secondary_unit
   |                secondary_unit
   | apragma
   | ; (* context_clause cannot be null *)

(* 2.4 *)
(* a *)
numeric_literal :
     decimal_literal
   | based_literal ;

(* 2.4.1 *)
(* a *)
decimal_literal :
     integer_number
   | real_number ;

(* 2.4.2 *)
(* a *)
based_literal :
     based_integer
   | based_real ;

(* 2.8 *)
(* a *)
pragma_rep :
     pragma_rep apragma
   | ;

apragma :
     RWpragma identifier                                                 semicolon
   | RWpragma identifier left_paren argument_association_rep right_paren semicolon
   | assert_pragma ;

(* special production since "assert" is a reserved word in SPARK *)
assert_pragma :
     RWpragma RWassert left_paren argument_association_rep right_paren semicolon ;

argument_association_rep :
     argument_association_rep comma argument_association
   |                                argument_association ;

(* b *)
argument_association :
     identifier arrow ADA_expression
   |                  ADA_expression ;

(* 3.0 *)

(* ------------------------------------------------------------------
   The following rule is not used in the grammar definition
   declaration : program_declaration | proof_declaration
   ------------------------------------------------------------------*)

(* 3.1 *)
(* a *)
basic_declaration :
     object_declaration
   | full_type_declaration
   | subtype_declaration ;

(* 3.2 *)
(* a *)
object_declaration :
     constant_declaration
   | variable_declaration ;

(* b *)
constant_declaration :
     identifier_list colon RWconstant type_mark becomes expression semicolon
   | identifier_list colon RWconstant           becomes expression semicolon ;

(* c *)
variable_declaration :
     identifier_list colon           type_mark                    semicolon
   | identifier_list colon           type_mark becomes expression semicolon
   | identifier_list colon RWaliased type_mark                    semicolon
   | identifier_list colon RWaliased type_mark becomes expression semicolon ;

(* d *)
identifier_list :
     identifier_list comma identifier
   |                       identifier ;

(* 3.3.1 *)
(* b *)
full_type_declaration :
     RWtype identifier RWis type_definition semicolon
   | task_type_declaration
   | protected_type_declaration ;

(* c *)
type_definition :
     enumeration_type_definition
   | integer_type_definition
   | derived_type_definition
   | real_type_definition
   | array_type_definition
   | record_type_definition
   | modular_type_definition
   | type_extension ; (*tag*)

(*tag*)
type_extension :
     private_type_extension
   | record_type_extension ;

(*tag*)
private_type_extension :
     RWnew type_mark RWwith RWprivate ;

(*tag*)
record_type_extension :
     RWnew type_mark RWwith record_definition ;

(* 3.3.2 *)
(* a *)
subtype_declaration :
     RWsubtype identifier RWis subtype_indication semicolon ;

(* b *)
subtype_indication :
     type_mark constraint
   | type_mark ;

(* c *)
type_mark :
     dotted_simple_name ;

(* d *)
constraint :
     range_constraint
   | floating_point_constraint
   | fixed_point_constraint
   | index_or_discriminant_constraint ;

(* 3.4 *)

(* 3.5 *)
(* a *)
range_constraint :
     RWrange arange ;

(* b *)
arange :
     attribute
   | simple_expression double_dot simple_expression ;

(* 3.5.1 *)
(* a *)
enumeration_type_definition :
     left_paren enumeration_literal_specification comma enumeration_type_definition_rep right_paren
   | left_paren enumeration_literal_specification                                       right_paren ;

enumeration_type_definition_rep :
     enumeration_type_definition_rep comma enumeration_literal_specification
   |                                       enumeration_literal_specification  ;

(* b *)
enumeration_literal_specification :
     enumeration_literal ;

(* c *)
enumeration_literal :
     identifier ;

(* 3.5.4 *)
(* a *)
integer_type_definition :
     range_constraint ;

derived_type_definition :
     RWnew type_mark
   | RWnew type_mark range_constraint
   | RWnew type_mark floating_point_constraint ; (* allow in grammar, but reject in Sem *)

modular_type_definition :
     RWmod simple_expression ;

(* 3.5.6 *)
(* a *)
real_type_definition :
     floating_point_constraint
   | fixed_point_constraint ;

(* 3.5.7 *)
(* a *)
floating_point_constraint :
     floating_accuracy_definition
   | floating_accuracy_definition range_constraint ;

(* b *)
floating_accuracy_definition :
     RWdigits simple_expression ;

(* 3.5.9 *)
(* a *)
fixed_point_constraint :
     fixed_accuracy_definition
   | fixed_accuracy_definition range_constraint ;

(* b *)
fixed_accuracy_definition :
     RWdelta simple_expression ;

(* 3.6 *)
(* a *)
array_type_definition :
     unconstrained_array_definition
   | constrained_array_definition ;

(* b *)
unconstrained_array_definition :
     RWarray left_paren unconstrained_array_definition_rep right_paren RWof type_mark ;

unconstrained_array_definition_rep :
     unconstrained_array_definition_rep comma index_subtype_definition
   |                                          index_subtype_definition  ;

(* c *)
constrained_array_definition :
     RWarray index_constraint RWof type_mark ;

(* d *)
index_subtype_definition :
     type_mark RWrange box ;

(* e *)
index_constraint :
     left_paren index_constraint_rep right_paren ;

index_constraint_rep :
     index_constraint_rep comma type_mark
   |                            type_mark ;

(* 3.7 *)
(* discriminants for protected declarations *)

known_discriminant_part :
     left_paren known_discriminant_part_rep right_paren ;

known_discriminant_part_rep :
     known_discriminant_part_rep semicolon discriminant_specification
   |                                       discriminant_specification ;

discriminant_specification :
     identifier_list colon type_mark
   | identifier_list colon access_definition ;

access_definition :  (* 3.10 *)
     RWaccess type_mark ;

(* 3.7.1 *)
index_or_discriminant_constraint :
     left_paren discriminant_association right_paren ;

discriminant_association :
     named_argument_association
   | positional_argument_association ;

(* 3.8 *)

record_type_definition :
     tag_option record_definition ;

record_definition :
     RWrecord component_list RWend RWrecord
   | null_record ;

null_record :
     RWnull RWrecord
   | RWrecord RWnull semicolon RWend RWrecord ;

component_list :
     component_list component_declaration
   |                component_declaration ;

(* c *)
component_declaration :
     identifier_list colon component_subtype_definition semicolon ;

(* d *)
component_subtype_definition :
     type_mark ;

(* 3.9 *)
(* a *)
declarative_part :
     renaming_declaration_rep initial_declarative_item_rep later_declarative_item_rep
   |                          initial_declarative_item_rep later_declarative_item_rep
   | renaming_declaration_rep initial_declarative_item_rep
   |                          initial_declarative_item_rep
   | renaming_declaration_rep                              later_declarative_item_rep
   |                                                       later_declarative_item_rep
   | renaming_declaration_rep ;

initial_declarative_item_rep :
     initial_declarative_item_rep basic_declarative_item
   |                              basic_declarative_item
   | initial_declarative_item_rep package_declaration
   |                              package_declaration
   | initial_declarative_item_rep renaming_declaration
   | initial_declarative_item_rep use_type_clause
   | initial_declarative_item_rep proof_renaming_declaration
   | initial_declarative_item_rep apragma
   | generic_package_instantiation ;

(* b *)
basic_declarative_item :
     basic_declaration
   | justification_statement
   | representation_clause
   | basic_proof_declaration ;

later_declarative_item_rep :
     later_declarative_item_rep later_declarative_item
   |                            later_declarative_item
   | later_declarative_item_rep apragma ;

later_declarative_item :
     abody
   | proof_function_declaration
   | generic_subprogram_instantiation ;

abody :
     proper_body
   | body_stub ;

proper_body :
     subprogram_body
   | package_body
   | task_body
   | protected_body ;

basic_proof_declaration :
     proof_type_declaration
   | type_assertion
   | object_assertion
   | proof_constant_declaration ;

type_assertion :
     base_type_assertion
   | alwaysvalid_variable_assertion ;

base_type_assertion :
     proof_context RWassert dotted_simple_name attribute_ident RWis identifier semicolon annotation_end ;

alwaysvalid_variable_assertion :
     proof_context RWassert dotted_simple_name attribute_ident semicolon annotation_end ;

object_assertion :
     proof_context RWfor simple_name_rep RWdeclare identifier semicolon annotation_end ;

proof_type_declaration :
     proof_context RWtype identifier RWis proof_type_definition annotation_end ;

proof_type_definition :
     RWabstract semicolon ;

proof_constant_declaration :
     proof_context identifier_list colon RWconstant type_mark becomes annotation_expression semicolon annotation_end ;

proof_function_declaration :
     proof_context function_specification semicolon annotation_end function_constraint ;

annotation_range_constraint :
     RWrange annotation_arange ;

annotation_arange :
     annotation_attribute
   | annotation_simple_expression double_dot annotation_simple_expression ;

(*------------------------Annotation Expressions------------------------*)

annotation_name :
     annotation_simple_name
   | annotation_selected_component
   | annotation_name left_paren annotation_name_argument_list right_paren
   | composite_update ;

composite_update :
     annotation_name square_open store_rep square_close ;

store_rep :
     store_rep semicolon store
   |                     store ;

store :
     store_list arrow annotation_expression ;

store_list :
     store_list comma annotation_expression
   |                  annotation_expression ;


(* b *)
annotation_simple_name :
     identifier
   | identifier tilde
   | identifier percent ;

(* c *)
annotation_prefix :
     annotation_name ;

annotation_name_argument_list :
     annotation_named_argument_association
   | annotation_positional_argument_association ;

annotation_named_argument_association :
     annotation_named_argument_association comma annotation_simple_name arrow annotation_expression
   |                                             annotation_simple_name arrow annotation_expression ;

annotation_positional_argument_association :
     annotation_positional_argument_association comma annotation_expression
   |                                                  annotation_expression ;

annotation_selected_component :
     annotation_prefix point annotation_selector ;

annotation_selector :
     annotation_simple_name ;

annotation_attribute :
     annotation_prefix annotation_attribute_designator ;

annotation_attribute_designator :
     annotation_attribute_designator attribute_ident annotation_attribute_designator_opt
   |                                 attribute_ident annotation_attribute_designator_opt ;

annotation_attribute_designator_opt :
     left_paren annotation_expression                             right_paren
   | left_paren annotation_expression comma annotation_expression right_paren
   | ;

annotation_aggregate :
     left_paren annotation_component_association right_paren ;

annotation_component_association :
     RWothers arrow annotation_aggregate_or_expression
   | annotation_named_association
   | annotation_positional_association ;

annotation_named_association :
     annotation_named_association_rep comma RWothers arrow annotation_aggregate_or_expression
   | annotation_named_association_rep ;

annotation_named_association_rep :
     annotation_named_association_rep comma annotation_aggregate_choice_rep arrow annotation_aggregate_or_expression
   |                                        annotation_aggregate_choice_rep arrow annotation_aggregate_or_expression ;

annotation_aggregate_choice_rep :
     annotation_aggregate_choice_rep vertical_bar annotation_aggregate_choice
   |                                              annotation_aggregate_choice ;

annotation_aggregate_choice :
     annotation_simple_expression
   | annotation_simple_expression annotation_range_constraint
   | annotation_simple_expression double_dot annotation_simple_expression ;

annotation_positional_association :
     annotation_aggregate_or_expression    comma RWothers arrow annotation_aggregate_or_expression
   | annotation_positional_association_rep comma RWothers arrow annotation_aggregate_or_expression
   | annotation_positional_association_rep ;

annotation_positional_association_rep :
     annotation_positional_association_rep comma annotation_aggregate_or_expression
   | annotation_aggregate_or_expression    comma annotation_aggregate_or_expression ;

annotation_aggregate_or_expression :
     annotation_aggregate
   | annotation_expression ;

annotation_expression :
     annotation_relation
   | annotation_relation RWand            annotation_expression_rep1
   | annotation_relation RWandthen        annotation_expression_rep2
   | annotation_relation RWor             annotation_expression_rep3
   | annotation_relation RWorelse         annotation_expression_rep4
   | annotation_relation RWxor            annotation_expression_rep5
   | annotation_relation implies          annotation_expression_rep6
   | annotation_relation is_equivalent_to annotation_expression_rep7
   | quantified_expression ;

annotation_expression_rep1 :
     annotation_expression_rep1 RWand annotation_relation
   |                                  annotation_relation ;

annotation_expression_rep2 :
     annotation_expression_rep2 RWandthen annotation_relation
   |                                      annotation_relation ;

annotation_expression_rep3 :
     annotation_expression_rep3 RWor annotation_relation
   |                                 annotation_relation ;

annotation_expression_rep4 :
     annotation_expression_rep4 RWorelse annotation_relation
   |                                     annotation_relation ;

annotation_expression_rep5 :
     annotation_expression_rep5 RWxor annotation_relation
   |                                  annotation_relation ;

annotation_expression_rep6 :
     annotation_expression_rep6 implies annotation_relation
   |                                    annotation_relation ;

annotation_expression_rep7 :
     annotation_expression_rep7 RWxor annotation_relation
   |                                  annotation_relation ;

annotation_relation :
     annotation_simple_expression
   | annotation_simple_expression relational_operator annotation_simple_expression
   | annotation_simple_expression inside  annotation_arange
   | annotation_simple_expression outside annotation_arange
   | annotation_simple_expression inside  annotation_name
   | annotation_simple_expression outside annotation_name ;

annotation_simple_expression :
     annotation_simple_expression binary_adding_operator annotation_term
   | annotation_simple_expression_opt ;

annotation_simple_expression_opt :
     unary_adding_operator annotation_term
   |                       annotation_term ;

annotation_term :
     annotation_term multiplying_operator annotation_factor
   |                                      annotation_factor ;

annotation_factor :
           annotation_primary
   |       annotation_primary double_star annotation_primary
   | RWabs annotation_primary
   | RWnot annotation_primary ;

annotation_primary :
     numeric_literal
   | character_literal
   | string_literal
   | annotation_name
   | annotation_qualified_expression
   | left_paren annotation_expression right_paren
   | annotation_attribute ;

annotation_qualified_expression :
     annotation_name apostrophe annotation_aggregate
   | annotation_name apostrophe annotation_extension_aggregate
   | annotation_name apostrophe left_paren annotation_expression right_paren ;

annotation_extension_aggregate :
     left_paren annotation_ancestor_part RWwith annotation_record_component_association right_paren
   | left_paren annotation_ancestor_part RWwith RWnull RWrecord                         right_paren ;

annotation_ancestor_part :
     annotation_expression ;

annotation_record_component_association :
     annotation_named_record_component_association
   | annotation_positional_record_component_association ;

annotation_positional_record_component_association :
     annotation_positional_record_component_association comma annotation_expression
   |                                                          annotation_expression ;

annotation_named_record_component_association :
     annotation_named_record_component_association comma record_component_selector_name arrow annotation_expression
   |                                                     record_component_selector_name arrow annotation_expression ;

record_component_selector_name :
     identifier ;

(*----------------------------------------------------------------------*)
(* 4.1 *)
(* a *)
name :
     simple_name
   | selected_component
   | name left_paren name_argument_list right_paren ;

(* b *)
simple_name :
     identifier ;

dotted_simple_name :
     dotted_simple_name point identifier
   |                          identifier ;

(* c *)
prefix :
     name ;

name_argument_list :
     named_argument_association
   | positional_argument_association ;

named_argument_association :
     named_argument_association comma simple_name arrow expression
   |                                  simple_name arrow expression ;

positional_argument_association :
     positional_argument_association comma expression
   |                                       expression ;

(* 4.1.1 *)
(* a *)

(* 4.1.3 *)
(* a *)
selected_component :
     prefix point selector ;

(* b *)
selector :
     simple_name ;

(* 4.1.4 *)
(* a *)
attribute :
     prefix            attribute_designator
   | character_literal attribute_designator ;

(* b *)
attribute_designator :
     attribute_designator attribute_ident attribute_designator_opt
   |                      attribute_ident attribute_designator_opt ;

attribute_designator_opt :
     left_paren expression                  right_paren
   | left_paren expression comma expression right_paren
   | ;

(* 4.3 *)
(* a *)
aggregate :
     left_paren component_association right_paren ;

(* b *)
component_association :
     RWothers arrow aggregate_or_expression
   | named_association
   | positional_association ;

(* c *)
named_association :
     named_association_rep comma RWothers arrow aggregate_or_expression
   | named_association_rep ;

named_association_rep :
     named_association_rep comma aggregate_choice_rep arrow aggregate_or_expression
   |                             aggregate_choice_rep arrow aggregate_or_expression ;

aggregate_choice_rep :
     aggregate_choice_rep vertical_bar aggregate_choice
   |                                   aggregate_choice ;

(* d *)
aggregate_choice :
     simple_expression
   | simple_expression range_constraint
   | simple_expression double_dot simple_expression ;

(* e *)
positional_association :
     aggregate_or_expression    comma RWothers arrow aggregate_or_expression
   | positional_association_rep comma RWothers arrow aggregate_or_expression
   | positional_association_rep ;

positional_association_rep :
     positional_association_rep comma aggregate_or_expression
   | aggregate_or_expression    comma aggregate_or_expression ;

aggregate_or_expression :
     aggregate
   | expression ;

(* 4.4 *)
(* a *)
expression :
     relation
   | relation RWand     expression_rep1
   | relation RWandthen expression_rep2
   | relation RWor      expression_rep3
   | relation RWorelse  expression_rep4
   | relation RWxor     expression_rep5 ;

expression_rep1 :
     expression_rep1 RWand relation
   |                       relation ;

expression_rep2 :
     expression_rep2 RWandthen relation
   |                           relation ;

expression_rep3 :
     expression_rep3 RWor relation
   |                      relation ;

expression_rep4 :
     expression_rep4 RWorelse relation
   |                          relation ;

expression_rep5 :
     expression_rep5 RWxor relation
   |                       relation ;

(* b *)
relation :
     simple_expression
   | simple_expression relational_operator simple_expression
   | simple_expression inside  arange
   | simple_expression outside arange
   | simple_expression inside  name
   | simple_expression outside name ;

inside :
     RWin ;

outside :
     RWnotin ;

(* c *)
simple_expression :
     simple_expression binary_adding_operator term
   | simple_expression_opt ;

simple_expression_opt :
     unary_adding_operator term
   |                       term ;

(* d *)
term :
     term multiplying_operator factor
   |                           factor ;

(* e *)
factor :
           primary
   |       primary double_star primary
   | RWabs primary
   | RWnot primary ;

(* f *)
primary :
     numeric_literal
   | character_literal
   | string_literal
   | name
   | qualified_expression
   | left_paren expression right_paren
   | attribute ;

(* 4.5 *)
(* a *)

(* b *)
relational_operator :
     equals
   | not_equal
   | less_than
   | less_or_equal
   | greater_than
   | greater_or_equal ;

(* c *)
binary_adding_operator :
     plus
   | minus
   | ampersand ;

(* d *)
unary_adding_operator :
     plus
   | minus ;

(* e *)
multiplying_operator :
     multiply
   | divide
   | RWmod
   | RWrem ;

(* f *)

(* 4.6 *)
(* a *)

(* 4.7 *)
(* a *)
qualified_expression :
     name apostrophe aggregate
   | name apostrophe extension_aggregate
   | name apostrophe left_paren expression right_paren ;

extension_aggregate :
     left_paren ancestor_part RWwith record_component_association right_paren
   | left_paren ancestor_part RWwith RWnull RWrecord              right_paren ;

ancestor_part :
     expression ;

record_component_association :
     named_record_component_association
   | positional_record_component_association ;

positional_record_component_association :
     positional_record_component_association comma expression
   |                                               expression ;

named_record_component_association :
     named_record_component_association comma record_component_selector_name arrow expression
   |                                          record_component_selector_name arrow expression ;


(* 5. *)
(* a *)
sequence_of_statements :
     sequence_of_statements statement
   |                        statement ;

(* b *)
label :
     left_label_paren simple_name right_label_paren ;

sequence_of_labels :
     sequence_of_labels label
   |                    label ;

statement :
     sequence_of_labels simple_statement
   |                    simple_statement
   | sequence_of_labels compound_statement
   |                    compound_statement
   | proof_statement
   | justification_statement
   | sequence_of_labels apragma
   |                    apragma ;

(* 5.1 *)
(* a *)
simple_statement :
     null_statement
   | assignment_statement
   | procedure_call_statement
   | exit_statement
   | return_statement
   | delay_statement ;

(* b *)
compound_statement :
     if_statement
   | case_statement
   | loop_statement ;

(* c *)
null_statement :
     RWnull semicolon ;

(* 5.2 *)
(* a *)
(* The unconstrained_array_assignment is a special case where we allow an unqualified
   aggregate only where it is being used to fully assign to an out parameter
   of an unconstrained array type. *)
unconstrained_array_assignment :
     name becomes left_paren RWothers arrow expression right_paren semicolon ;

assignment_statement :
     name becomes expression semicolon
   | unconstrained_array_assignment ;

(* 5.3 *)
(* a *)
if_statement :
     RWif condition RWthen sequence_of_statements elsif_part else_part RWend RWif semicolon ;

elsif_part :
     elsif_part RWelsif condition RWthen sequence_of_statements
   | ;

else_part :
     RWelse sequence_of_statements
   | ;

(* b *)
condition :
     expression ;

(* 5.4 *)
(* a *)
case_statement :
     RWcase expression RWis alternatives others_part RWend RWcase semicolon ;

alternatives :
     alternatives case_statement_alternative
   |              case_statement_alternative ;

(* b *)
case_statement_alternative :
     RWwhen case_statement_alternative_rep arrow sequence_of_statements ;

case_statement_alternative_rep :
     case_statement_alternative_rep vertical_bar case_choice
   |                                             case_choice ;

(* c *)
case_choice :
     simple_expression
   | simple_expression range_constraint
   | simple_expression double_dot simple_expression ;

others_part :
     RWwhen RWothers arrow sequence_of_statements
   | ;

(* 5.5 *)
(* a *)

(* null production to provide a placeholder in infinite loops where we can model a
       syntactic exit to keep the flow analyser happy *)
end_of_loop :
     ;

loop_statement :
     simple_name colon loop_statement_opt RWloop sequence_of_statements end_of_loop RWend RWloop simple_name semicolon
   |                   loop_statement_opt RWloop sequence_of_statements end_of_loop RWend RWloop             semicolon ;

loop_statement_opt :
     iteration_scheme
   | iteration_scheme loop_invariant
   | ;

(* b *)
iteration_scheme :
     RWwhile condition
   | RWfor loop_parameter_specification ;

(* c *)
loop_parameter_specification :
     identifier forward  type_mark
   | identifier forward  type_mark RWrange arange
   | identifier backward type_mark
   | identifier backward type_mark RWrange arange ;

forward :
     RWin ;

backward :
     RWin RWreverse ;

(* d *)
loop_invariant :
     assert_statement ;

(* 5.7 *)
(* a *)
exit_statement :
     RWexit                              semicolon
   | RWexit             RWwhen condition semicolon
   | RWexit simple_name                  semicolon
   | RWexit simple_name RWwhen condition semicolon ;

(* 5.8 *)
(* a *)
return_statement :
     RWreturn expression semicolon ;

(* 5.10 *)
proof_statement :
     assert_statement
   | assume_statement
   | check_statement ;

assert_statement :
     proof_context RWassert predicate semicolon annotation_end ;

assume_statement :
     proof_context RWassume predicate semicolon annotation_end ;

check_statement :
     proof_context RWcheck predicate semicolon annotation_end ;

(* justification of expected warnings *) (*PNA--------------------*)
justification_statement :
     start_justification
   | end_justification ;

start_justification :
     proof_context RWaccept justification_rep semicolon annotation_end ;

justification_rep :
     justification_rep ampersand justification_clause
   |                             justification_clause ;

justification_clause :
     identifier comma numeric_literal comma justification_opt justification_string |
     identifier comma numeric_literal comma justification_all justification_string ;

dotted_simple_name_list :
     dotted_simple_name_list comma dotted_simple_name_or_null
   |                               dotted_simple_name_or_null ;

dotted_simple_name_or_null :
     dotted_simple_name
   | null_name ;

null_name :
     RWnull ;

justification_opt :
     dotted_simple_name_list comma
   | ;

justification_all :
     RWall comma ;

justification_string :
     string_literal
   | string_literal comma justification_string ;

end_justification :
     proof_context RWend RWaccept semicolon annotation_end ;

(*------------------PNA *)

(* 6.1 *)
(* a *)

overriding_indicator :
     RWnot RWoverriding
   |       RWoverriding ;

subprogram_declaration :
     overriding_indicator procedure_specification semicolon procedure_annotation
   |                      procedure_specification semicolon procedure_annotation
   | overriding_indicator function_specification  semicolon function_annotation
   |                      function_specification  semicolon function_annotation
   | proof_function_declaration ;

not_overriding_subprogram_declaration :
     procedure_specification semicolon procedure_annotation
   | function_specification  semicolon function_annotation
   | proof_function_declaration ;

(* b *)
subprogram_specification :
     procedure_specification
   | function_specification ;

(* c *)
procedure_specification :
     RWprocedure simple_name
   | RWprocedure simple_name formal_part ;

(* d *)
function_specification :
     RWfunction designator formal_part RWreturn type_mark
   | RWfunction designator             RWreturn type_mark ;

(* e *)
designator :
     identifier ;

(* f *)
operator_symbol :
     string_literal ;

(* g *)
formal_part :
     left_paren formal_part_rep right_paren ;

formal_part_rep :
     formal_part_rep semicolon parameter_specification
   |                           parameter_specification ;

(* h *)
parameter_specification :
     identifier_list colon mode type_mark ;

(* i *)
mode :
     in_mode
   | inout_mode
   | out_mode
   | ;

in_mode :
     RWin ;

inout_mode :
     RWin RWout ;

out_mode :
     RWout ;


(* 6.1.1 *)
(* a *)
procedure_annotation :
                                                                    procedure_constraint
   |                                             declare_annotation procedure_constraint
   |                         dependency_relation                    procedure_constraint
   |                         dependency_relation declare_annotation procedure_constraint
   | moded_global_definition                                        procedure_constraint
   | moded_global_definition                     declare_annotation procedure_constraint
   | moded_global_definition dependency_relation                    procedure_constraint
   | moded_global_definition dependency_relation declare_annotation procedure_constraint ;

(* b *)
function_annotation :
                             function_constraint
   | moded_global_definition function_constraint ;

(* 6.1.2 *)
(* a *)
moded_global_definition :
     annotation_start RWglobal global_definition_rep annotation_end ;

global_definition_rep :
     global_definition_rep global_variable_clause
   |                       global_variable_clause ;

global_variable_clause :
     mode global_variable_list semicolon ;

(* b *)
global_variable_list :
     global_variable_list comma global_variable
   |                            global_variable ;

(* c *)
global_variable :
     entire_variable ;

(* d *)
entire_variable :
     dotted_simple_name ;

(* e *)
dependency_relation :
     annotation_start RWderives dependency_relation_opt semicolon annotation_end ;

dependency_relation_opt :
     dependency_relation_rep
   | dependency_relation_rep ampersand null_import_list
   |                                   null_import_list
   | ;

dependency_relation_rep :
     dependency_relation_rep ampersand dependency_clause
   |                                   dependency_clause ;

(* f *)
dependency_clause :
     dependency_clause_optrep RWfrom dependency_clause_opt ;

dependency_clause_opt :
     multiply comma dependency_clause_optrep
   |                dependency_clause_optrep
   | multiply
   | ;

dependency_clause_optrep :
     dependency_clause_optrep comma entire_variable
   |                                entire_variable ;

null_import_list :
     RWnull RWfrom dependency_clause_optrep ;

(* 6.1.3 *)

(* c *)
precondition :
     annotation_start RWpre predicate semicolon annotation_end ;

(* d *)
postcondition :
     annotation_start RWpost predicate semicolon annotation_end ;

procedure_constraint :
     precondition postcondition
   | precondition
   |              postcondition
   | ;

function_constraint :
     precondition return_expression
   | precondition
   |              return_expression
   | ;

return_expression :
     annotation_start RWreturn annotation_expression       semicolon annotation_end
   | annotation_start RWreturn simple_name arrow predicate semicolon annotation_end ;

(* 6.1.4 *)
(* a *)
(* Note we use RWdeclare here to avoid potential ambiguity between this and
   base_type_assertion, which uses RWassert *)

declare_annotation :
     annotation_start RWdeclare property_list semicolon annotation_end ;


(* 6.3 *)
(* a *)
subprogram_body :
     overriding_indicator procedure_specification procedure_annotation RWis subprogram_implementation
   | overriding_indicator function_specification  function_annotation  RWis subprogram_implementation
   |                      procedure_specification procedure_annotation RWis subprogram_implementation
   |                      function_specification  function_annotation  RWis subprogram_implementation ;

not_overriding_subprogram_body :
     procedure_specification procedure_annotation RWis subprogram_implementation
   | function_specification  function_annotation  RWis subprogram_implementation ;

(* b *)
subprogram_implementation :
     pragma_rep declarative_part RWbegin sequence_of_statements RWend designator             semicolon
   | pragma_rep declarative_part RWbegin sequence_of_statements RWexception      hidden_part semicolon
   | pragma_rep                  RWbegin sequence_of_statements RWend designator             semicolon
   | pragma_rep                  RWbegin sequence_of_statements RWexception      hidden_part semicolon
   | pragma_rep                  RWbegin code_insertion         RWend designator             semicolon
   | pragma_rep                                                                  hidden_part semicolon ;

(* c *)
code_insertion :
     code_insertion apragma
   | code_insertion code_statement
   |                code_statement ;

(* d *)
hidden_part :
     hide_directive ;

(* 6.4 *)
(* a *)
procedure_call_statement :
     name semicolon ;

(* c *)

(* 7.1 *)
(* a *)
package_declaration :
     inherit_clause package_specification semicolon
   |                package_specification semicolon ;

private_package_declaration :
     inherit_clause RWprivate package_specification semicolon
   |                RWprivate package_specification semicolon ;

(* b *)
package_specification :
     RWpackage dotted_simple_name package_annotation RWis visible_part RWprivate private_part
   | RWpackage dotted_simple_name package_annotation RWis visible_part RWend dotted_simple_name ;

(* c *)
visible_part :
     visible_part_rep ;

visible_part_rep :
     visible_part_rep basic_declarative_item
   | visible_part_rep private_type_declaration
   | visible_part_rep deferred_constant_declaration
   | visible_part_rep subprogram_declaration
   | visible_part_rep generic_subprogram_instantiation
   | visible_part_rep apragma
   | visible_part_rep renaming_declaration
   | ;

(* d *)
private_part :
     basic_declarative_item_rep RWend dotted_simple_name
   | hidden_part ;

basic_declarative_item_rep :
     basic_declarative_item_rep subprogram_declaration
   | basic_declarative_item_rep generic_subprogram_instantiation
   | basic_declarative_item_rep basic_declarative_item
   | basic_declarative_item_rep apragma
   | ;

(* e *)
package_body :
     RWpackage RWbody dotted_simple_name                       RWis package_implementation semicolon
   | RWpackage RWbody dotted_simple_name refinement_definition RWis package_implementation semicolon ;

refinement_definition :
     annotation_start RWown refinement_clause_rep semicolon annotation_end ;

refinement_clause_rep :
     refinement_clause_rep ampersand refinement_clause
   |                                 refinement_clause ;

refinement_clause :
     identifier RWis constituent_list
   | identifier ; (* illegal, but accept here and rejected in wellformedness *)

constituent_list :
     constituent_list comma own_variable_modifier entire_variable
   |                        own_variable_modifier entire_variable ;

(* f *)
package_implementation :
     pragma_rep declarative_part RWend   dotted_simple_name
   | pragma_rep                  RWend   dotted_simple_name
   | pragma_rep declarative_part RWbegin package_initialization
   | pragma_rep                  RWbegin package_initialization
   | hidden_part ;

(* g *)
package_initialization :
     sequence_of_statements RWend dotted_simple_name
   | hidden_part ;

use_type_clause :
     RWuse RWtype use_type_rep semicolon ;

use_type_rep :
     use_type_rep comma type_mark
   |                    type_mark ;

(* 7.2.1 *)
(* a *)
inherit_clause :
     annotation_start RWinherit inherit_clause_rep semicolon annotation_end ;

inherit_clause_rep :
     inherit_clause_rep comma dotted_simple_name
   |                          dotted_simple_name ;


(* 7.2.2 *)
(* a *)
package_annotation :
     own_variable_clause initialization_specification
   | own_variable_clause
   | ;


(* 7.2.3 *)
(* a *)
own_variable_clause :
     annotation_start RWown own_variable_clause_rep annotation_end ;

own_variable_clause_rep :
     own_variable_clause_rep own_variable_specification
   |                         own_variable_specification ;

(* b *)
own_variable_specification :
     own_variable_list                                                      semicolon
   | own_variable_list colon type_mark                                      semicolon
   | own_variable_list                 left_paren property_list right_paren semicolon
   | own_variable_list colon type_mark left_paren property_list right_paren semicolon ;

(* c *)
own_variable_list :
     own_variable_list comma own_variable_modifier own_variable
   |                         own_variable_modifier own_variable ;

own_variable_modifier :
     mode
   | protected_modifier
   | protected_moded_modifier
   | task_modifier ;

protected_moded_modifier :
     protected_modifier in_mode
   | protected_modifier out_mode ;

protected_modifier :
     RWprotected ;

task_modifier :
     RWtask ;

(* d *)
own_variable :
     simple_name ;


property_list :
     property_rep ;

property_rep :
     property_rep comma property
   |                    property ;

property :
     name_property
   | name_value_property ;

name_property :
     RWdelay
   | identifier ;

name_value_property :
     identifier arrow annotation_aggregate_or_expression ;

(* 7.2.4 *)
(* a *)
initialization_specification :
     annotation_start RWinitializes package_variable_list semicolon annotation_end
   | annotation_start RWinitializes package_variable_list semicolon annotation_end postcondition ;

(* b *)
package_variable_list :
     package_variable_list comma own_variable
   |                             own_variable ;


(* 7.4 *)
(* a *)
private_type_declaration :
     non_limited_private_type_declaration
   | limited_private_type_declaration ;

non_limited_private_type_declaration :
     RWtype identifier RWis tag_option RWprivate semicolon ;            (*tag*)

limited_private_type_declaration :
     RWtype identifier RWis tag_option RWlimited RWprivate semicolon ;  (*tag*)

(*tag*)
tag_option :
     non_abstract_tagged
   | abstract_tagged
   | non_tagged ;

non_abstract_tagged :
     RWtagged ;

abstract_tagged :
     RWabstract RWtagged ;

non_tagged :
     ;

(* b *)
deferred_constant_declaration :
     identifier_list colon RWconstant type_mark semicolon ;

(* 8.5 *)
renaming_declaration_rep :
     renaming_declaration_rep renaming_declaration
   | renaming_declaration_rep proof_renaming_declaration
   | renaming_declaration_rep apragma
   |                          renaming_declaration
   | proof_renaming_declaration ;

proof_renaming_declaration :
     proof_context function_specification RWrenames dotted_simple_name point simple_name semicolon annotation_end ;

(* a *)
renaming_declaration :
     RWfunction operator_symbol formal_part RWreturn type_mark RWrenames dotted_simple_name point operator_symbol semicolon
   | subprogram_specification                                  RWrenames dotted_simple_name point simple_name     semicolon
   | package_renaming_declaration                                                                                           ;

package_renaming_declaration :
     RWpackage identifier RWrenames dotted_simple_name semicolon ;


(* 9.1 *)
task_type_declaration :
     RWtask RWtype identifier                         task_type_annotation task_definition
   | RWtask RWtype identifier known_discriminant_part task_type_annotation task_definition ;

task_type_annotation :
     moded_global_definition dependency_relation declare_annotation
   | moded_global_definition dependency_relation
   | moded_global_definition                     declare_annotation
   | moded_global_definition ;

task_definition :
     RWis task_pragma RWend identifier semicolon ;

task_pragma :
     task_pragma apragma
   | priority_pragma ;

task_body :
     RWtask RWbody identifier procedure_annotation RWis subprogram_implementation ;

(* 9.4 *)
protected_type_declaration :
     RWprotected RWtype identifier                         RWis protected_definition
   | RWprotected RWtype identifier known_discriminant_part RWis protected_definition ;

protected_definition :
     protected_operation_declaration RWprivate protected_element_declaration RWend identifier semicolon
   | protected_operation_declaration                                         RWend identifier semicolon
   | protected_operation_declaration RWprivate hidden_part                                    semicolon ;

protected_operation_declaration :
     priority_pragma entry_or_subprogram protected_operation_declaration_rep ;

priority_pragma :
     RWpragma identifier left_paren expression right_paren semicolon ;

entry_or_subprogram :
     not_overriding_subprogram_declaration
   | entry_declaration ;

protected_operation_declaration_rep :
     protected_operation_declaration_rep apragma
   | protected_operation_declaration_rep not_overriding_subprogram_declaration
   | protected_operation_declaration_rep entry_declaration
   | ;

entry_declaration :
     entry_specification semicolon procedure_annotation ;

entry_specification :
     RWentry designator
   | RWentry designator formal_part ;

protected_element_declaration :
     protected_element_list ;

protected_element_list :
     protected_element_list protected_element
   |                        protected_element ;

protected_element :
     variable_declaration
   | justification_statement ;

protected_body :
     RWprotected RWbody identifier RWis protected_operation_item RWend identifier semicolon ;

protected_operation_item :
     protected_operation_item not_overriding_subprogram_body
  |  protected_operation_item entry_body
  |  ;

entry_body :
     entry_specification RWwhen identifier procedure_annotation RWis subprogram_implementation ;

(* 9.6 *)
delay_statement :
     RWdelay RWuntil expression semicolon ;

(* 10.1 *)

(* c *)
library_unit :
     package_declaration
   | private_package_declaration
   | main_program_declaration
   | generic_declaration
   | generic_package_instantiation ;

(* d *)
secondary_unit :
     library_unit_body
   | subunit ;

(* e *)
library_unit_body :
     package_body
   | generic_subprogram_body ;

generic_subprogram_body :
     not_overriding_subprogram_body ;

(* f *)
main_program_declaration :
     inherit_clause main_program_annotation                                             not_overriding_subprogram_body
   |                main_program_annotation                                             not_overriding_subprogram_body
   | inherit_clause main_program_annotation moded_global_definition dependency_relation not_overriding_subprogram_body
   | inherit_clause main_program_annotation moded_global_definition                     not_overriding_subprogram_body
   |                main_program_annotation moded_global_definition dependency_relation not_overriding_subprogram_body
   |                main_program_annotation moded_global_definition                     not_overriding_subprogram_body ;

(* g *)
main_program_annotation :
     annotation_start RWmain_program           annotation_end
   | annotation_start RWmain_program semicolon annotation_end ;

(* 10.1.1 *)
(* a *)

context_clause :
     with_clause context_clause_rep pragma_rep ;

(* b *)

with_clause :
     RWwith simple_name_rep semicolon ;

simple_name_rep :
     simple_name_rep comma dotted_simple_name
   |                       dotted_simple_name ;

context_clause_rep :
     context_clause_rep with_clause
   | context_clause_rep use_type_clause
   | ;

(* 10.2 *)
(* a *)

body_stub :
                          procedure_specification           procedure_annotation RWis RWseparate semicolon
   | overriding_indicator procedure_specification           procedure_annotation RWis RWseparate semicolon
   |                      procedure_specification semicolon procedure_annotation apragma
   |                      function_specification            function_annotation  RWis RWseparate semicolon
   | overriding_indicator function_specification            function_annotation  RWis RWseparate semicolon
   |                      function_specification  semicolon function_annotation  apragma
   | RWpackage RWbody     dotted_simple_name                                     RWis RWseparate semicolon
   | task_stub                                                                                   semicolon
   | protected_stub                                                                              semicolon ;

task_stub :
     RWtask RWbody identifier procedure_annotation RWis RWseparate ;

protected_stub :
     RWprotected RWbody identifier RWis RWseparate ;

(* b *)
subunit :
     RWseparate left_paren parent_unit_name right_paren proper_body ;

parent_unit_name :
     parent_unit_name point simple_name
   |                        simple_name ;

(* 12 *)

generic_declaration :
     generic_subprogram_declaration
   | generic_package_declaration ;

generic_subprogram_declaration :
     inherit_clause generic_formal_part not_overriding_subprogram_declaration
   |                generic_formal_part not_overriding_subprogram_declaration ;

generic_package_declaration :
     inherit_clause generic_formal_part package_specification semicolon
   |                generic_formal_part package_specification semicolon ;

generic_formal_part :
     RWgeneric generic_formal_part_rep ;

generic_formal_part_rep :
     generic_formal_part_rep formal_object_declaration
   | generic_formal_part_rep formal_type_declaration
   | ;

formal_object_declaration :
     identifier_list colon mode type_mark semicolon ;

formal_type_declaration :
     RWtype identifier RWis formal_type_definition semicolon ;

formal_type_definition :
     formal_private_type_definition
   | formal_discrete_type_definition
   | formal_signed_integer_type_definition
   | formal_modular_type_definition
   | formal_floating_point_definition
   | formal_ordinary_fixed_point_definition
   | formal_array_type_definition ;

formal_private_type_definition :
     RWprivate
   | RWlimited RWprivate ;

formal_discrete_type_definition :
     left_paren box right_paren ;

formal_signed_integer_type_definition :
     RWrange box ;

formal_modular_type_definition :
     RWmod box ;

formal_floating_point_definition :
     RWdigits box ;

formal_ordinary_fixed_point_definition :
     RWdelta box ;

formal_array_type_definition :
     array_type_definition ;

generic_package_instantiation :
     RWpackage dotted_simple_name package_annotation RWis RWnew identifier generic_actual_part semicolon
   | RWpackage dotted_simple_name package_annotation RWis RWnew identifier                     semicolon ;

generic_subprogram_instantiation :
     overriding_indicator procedure_specification procedure_annotation RWis RWnew dotted_simple_name generic_actual_part semicolon
   |                      procedure_specification procedure_annotation RWis RWnew dotted_simple_name generic_actual_part semicolon
   | overriding_indicator RWfunction simple_name function_constraint RWis RWnew dotted_simple_name generic_actual_part semicolon
   |                      RWfunction simple_name function_constraint RWis RWnew dotted_simple_name generic_actual_part semicolon ;

generic_actual_part :
     left_paren name_argument_list right_paren ;


(* 13.1 *)
(* a *)
representation_clause :
     attribute_definition_clause
   | enumeration_representation_clause
   | record_representation_clause
   | at_clause ;

(* 13.2 *)
(* a *)
attribute_definition_clause :
     RWfor attribute RWuse simple_expression semicolon ;

(* 13.3 *)
(* a *)
enumeration_representation_clause :
     RWfor simple_name RWuse aggregate semicolon ;

(* 13.4 *)
(* a *)
record_representation_clause :
     RWfor simple_name RWuse RWrecord            record_representation_clause_rep RWend RWrecord semicolon
   | RWfor simple_name RWuse RWrecord mod_clause record_representation_clause_rep RWend RWrecord semicolon ;

record_representation_clause_rep :
     record_representation_clause_rep component_clause
   | ;

(* b *)
mod_clause :
     RWat RWmod simple_expression semicolon ;

(* c *)
component_clause :
     simple_name RWat simple_expression RWrange arange semicolon ;

(* 13.5 *)
(* a *)
at_clause :
     RWfor simple_name RWuse RWat simple_expression semicolon ;

(* 13.8 *)
(* a *)
code_statement :
     name apostrophe aggregate semicolon ;

(* Full ADA expressions *)

ADA_name :
     identifier
   | character_literal
   | string_literal
   | ADA_name left_paren ADA_association_list right_paren
   | ADA_name point ADA_selector
   | ADA_name attribute_ident ;

ADA_selector :
     identifier
   | character_literal
   | string_literal
   | RWall ;

ADA_association_list :
     ADA_association_list comma ADA_association
   |                            ADA_association ;

ADA_association :
     ADA_choice_list arrow ADA_range
   | RWothers        arrow ADA_range
   |                       ADA_range ;

ADA_choice_list :
     ADA_choice_list vertical_bar ADA_range
   |                              ADA_range ;

ADA_range :
     ADA_name RWrange ADA_name
   | ADA_name RWrange ADA_simple_expression double_dot ADA_simple_expression
   |                  ADA_simple_expression
   |                  ADA_simple_expression double_dot ADA_simple_expression ;

ADA_expression :
     ADA_relation
   | ADA_relation RWand ADA_expression_rep1
   | ADA_relation RWandthen ADA_expression_rep2
   | ADA_relation RWor ADA_expression_rep3
   | ADA_relation RWorelse ADA_expression_rep4
   | ADA_relation RWxor ADA_expression_rep5 ;

ADA_expression_rep1 :
     ADA_expression_rep1 RWand ADA_relation
   |                           ADA_relation ;

ADA_expression_rep2 :
     ADA_expression_rep2 RWandthen ADA_relation
   |                               ADA_relation ;

ADA_expression_rep3 :
     ADA_expression_rep3 RWor ADA_relation
   |                          ADA_relation ;

ADA_expression_rep4 :
     ADA_expression_rep4 RWorelse ADA_relation
   |                              ADA_relation ;

ADA_expression_rep5 :
     ADA_expression_rep5 RWxor ADA_relation
   |                           ADA_relation ;

ADA_relation :
     ADA_simple_expression
   | ADA_simple_expression relational_operator ADA_simple_expression
   | ADA_simple_expression inside  ADA_range
   | ADA_simple_expression outside ADA_range ;

ADA_simple_expression :
     ADA_simple_expression_opt
   | ADA_simple_expression binary_adding_operator ADA_term ;

ADA_simple_expression_opt :
     unary_adding_operator ADA_term
   |                       ADA_term ;

ADA_term :
     ADA_term multiplying_operator ADA_factor
   |                               ADA_factor ;

ADA_factor :
           ADA_primary
   |       ADA_primary double_star ADA_primary
   | RWabs ADA_primary
   | RWnot ADA_primary ;

(* This production gives rise to a reduce/reduce conflict here, since a conflict-free *)
(* grammar can't differentiate between a one-element positional unqualified aggregate *)
(* and a parnentiesized expression.  e.g. "(A)" could be either.                      *)
(* We allow the conflict here, since an ADA_expression isn't semantically analyzed    *)
(* by the Examiner anyway, and it's more important to allow (legal) Ada syntax here.  *)
ADA_primary :
     numeric_literal
   |                     left_paren ADA_association_list right_paren
   |                     left_paren ADA_expression       right_paren
   | ADA_name
   | ADA_name apostrophe left_paren ADA_association_list right_paren
   | RWnull ;

(* Annotation Expressions *)
predicate :
     annotation_expression ;

quantified_expression :
     RWforall  identifier RWin type_mark RWrange annotation_arange arrow left_paren predicate right_paren
   | RWforall  identifier RWin type_mark                           arrow left_paren predicate right_paren
   | RWforsome identifier RWin type_mark RWrange annotation_arange arrow left_paren predicate right_paren
   | RWforsome identifier RWin type_mark                           arrow left_paren predicate right_paren ;

