-- package Ada95_Parser for SCATC DSK
-- Modified from the original by Richard Conn
--
-- Modified for AdaDoc by Vincent Decorges & Julien Burdy
-- Date : 10.4.02
-- Note : This version is not anymore compatible with
--        scayacc use ayacc instead
------------------------------------------------------------------------------
--
-- Single Character Tokens
--
%token '&' ''' '(' ')' '*' '+' ',' '-' '.' '/' ':' ';'
%token '<' '=' '>' '|'


-- Special Character or Two Character Tokens

%token ARROW DOUBLE_DOT DOUBLE_STAR ASSIGNMENT INEQUALITY
%token GREATER_THAN_OR_EQUAL LESS_THAN_OR_EQUAL
%token LEFT_LABEL_BRACKET RIGHT_LABEL_BRACKET
%token BOX


-- Reserved Words

%token ABORT_TOKEN ABS_TOKEN ABSTRACT_TOKEN ACCEPT_TOKEN  ACCESS_TOKEN
%token ALIASED_TOKEN ALL_TOKEN  AND_TOKEN ARRAY_TOKEN AT_TOKEN

%token BEGIN_TOKEN  BODY_TOKEN BOGUS_TOKEN

%token CASE_TOKEN  CONSTANT_TOKEN

%token DECLARE_TOKEN DELAY_TOKEN DELTA_TOKEN DIGITS_TOKEN DO_TOKEN

%token ELSE_TOKEN ELSIF_TOKEN END_TOKEN  ENTRY_TOKEN EXCEPTION_TOKEN
%token EXIT_TOKEN

%token FOR_TOKEN FUNCTION_TOKEN

%token GENERIC_TOKEN  GOTO_TOKEN

%token IF_TOKEN IN_TOKEN  IS_TOKEN

%token LIMITED_TOKEN LOOP_TOKEN

%token MOD_TOKEN

%token NEW_TOKEN NOT_TOKEN  NULL_TOKEN

%token OF_TOKEN OR_TOKEN OTHERS_TOKEN OUT_TOKEN

%token PACKAGE_TOKEN PRAGMA_TOKEN  PRIVATE_TOKEN PROCEDURE_TOKEN
%token PROTECTED_TOKEN

%token RAISE_TOKEN  RANGE_TOKEN RECORD_TOKEN REM_TOKEN RENAMES_TOKEN
%token REQUEUE_TOKEN RETURN_TOKEN REVERSE_TOKEN

%token SELECT_TOKEN  SEPARATE_TOKEN SUBTYPE_TOKEN

%token TAGGED_TOKEN TASK_TOKEN TERMINATE_TOKEN THEN_TOKEN TYPE_TOKEN

%token UNTIL_TOKEN USE_TOKEN

%token WHEN_TOKEN WHILE_TOKEN WITH_TOKEN

%token XOR_TOKEN


-- Additional Tokens

%token BASE
%token BASED_LITERAL

%token DECIMAL_LITERAL
%token DIGIT

%token EXTENDED_DIGIT
%token EXPONENT

%token IDENTIFIER
-- %token INTEGER

%token CHAR_LITERAL STRING_LITERAL

-- %token ERROR1 ERROR2  ERROR3  ERROR4  ERROR5  ERROR6  ERROR7  ERROR8
-- %token ERROR9 ERROR10 ERROR11 ERROR12 ERROR13 ERROR14 ERROR15

%start compilation

%with AdaDoc_Tree;
{
  Maximum_String_Length : constant := 200;
  type STRING_BUFFER is record
    Text        : STRING(1..Maximum_String_Length);
    Last        : NATURAL := 0;
  end record;

  subtype YYSTYPE is AdaDoc_Tree.Object_Token_Ptr;
}

%%


goal_symbol : compilation
	;

NUMERIC_LIT : DECIMAL_LITERAL
            {
               $$ := new Dummy_String_Token;
               Dummy_String_Token($$.all).Str :=
               To_Unbounded_String(Get_Token_Value);
            }
            | BASED_LITERAL
            {
               $$ := new Dummy_String_Token;
               Dummy_String_Token($$.all).Str :=
               To_Unbounded_String(Get_Token_Value);
            }
            ;

CHAR_LIT : CHAR_LITERAL
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String(Get_Token_Value);
   }
            ;

GT_GT : RIGHT_LABEL_BRACKET
      ;

LT_LT : LEFT_LABEL_BRACKET
      ;

GE : GREATER_THAN_OR_EQUAL
   ;

LT_EQ : LESS_THAN_OR_EQUAL
      ;

NE : INEQUALITY
   ;

CHAR_STRING : STRING_LITERAL
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String(Get_Token_Value);
   }
   ;

TIC : '''
    ;

pragma  : PRAGMA_TOKEN simple_name ';'
   {
      $$ := new Pragma_Decl_Token;
      Pragma_Decl_Token($$.all).Line_Number := Dummy_String_Token($2.all).Line_Number;
      Pragma_Decl_Token($$.all).Name := Dummy_String_Token($2.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }

   | PRAGMA_TOKEN simple_name '(' pragma_arg_s ')' ';'
	{
	   $$ := new Pragma_Decl_Token;
	   Pragma_Decl_Token($$.all).Line_Number := Dummy_String_Token($2.all).Line_Number;
      Pragma_Decl_Token($$.all).Name := Dummy_String_Token($2.all).Str;
      Pragma_Decl_Token($$.all).Decl := '(' & Dummy_String_Token($4.all).Str & ')';

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	;

pragma_arg_s : pragma_arg
   {
      $$ := $1;
   }
	| pragma_arg_s ',' pragma_arg
	{
	   $$ := $3;
	   Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ", " &
	                                     Dummy_String_Token($3.all).Str;

	}
	;

pragma_arg : expression
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str;
   }
	| simple_name ARROW expression
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & " => " &
                                        Dummy_String_Token($3.all).Str;
   }
	;

pragma_s :
	| pragma_s pragma
	;

decl    : object_decl
	| number_decl
	| type_decl
	| subtype_decl
	| subprog_decl
	| pkg_decl
	| task_decl
	| prot_decl
	| exception_decl
	| rename_decl
	| generic_decl
	| body_stub
	| error ';'
	;

object_decl : def_id_s ':' object_qualifier_opt object_subtype_def init_opt ';'
   {
      $$ := new Object_Declaration_Token;
      Object_Declaration_Token($$.all).Line_Number := Get_Current_Line;
      Object_Declaration_Token($$.all).Def_ID_S := Def_ID_S_Token_Ptr($1);
      Object_Declaration_Token($$.all).Qualifier := Object_Qualifier_Token_Ptr($3);
      Object_Declaration_Token($$.all).Subtype_Def := Dummy_String_Token($4.all).Str;
      Object_Declaration_Token($$.all).Init := Dummy_String_Token($5.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
	};

def_id_s : def_id

   {
      $$ := new Def_ID_S_Token;
      Def_ID_S_Token($$.all).Line_Number := Get_Current_Line;
      Def_ID_S_Token($$.all).Str := Dummy_String_Token($1.all).Str;
   }
	| def_id_s ',' def_id
	{
	   $$ := new Def_ID_S_Token;
	   Def_ID_S_Token($$.all).Line_Number := Get_Current_Line;
	   Def_ID_S_Token($$.all).Next_ID := Def_ID_S_Token_Ptr($1);
	   Def_ID_S_Token($$.all).Str := Dummy_String_Token($3.all).Str;
	}
	;

def_id  : identifier

   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Line_Number := Get_Current_Line;
      Dummy_String_Token($$.all).Str := To_Unbounded_String(Get_Token_Value);
   };

object_qualifier_opt :
   {
      $$ := new Object_Qualifier_Token;
      Object_Qualifier_Token($$.all).Qualifier := (others => False);
   }
	| ALIASED_TOKEN
	{
      $$ := new Object_Qualifier_Token;
      Object_Qualifier_Token($$.all).Qualifier := (Aliased_Qualifier => True,
                                                   Constant_Qualifier => False);
   }
	| CONSTANT_TOKEN
	{
      $$ := new Object_Qualifier_Token;
      Object_Qualifier_Token($$.all).Qualifier := (Aliased_Qualifier => False,
                                                   Constant_Qualifier => True);
   }
	| ALIASED_TOKEN CONSTANT_TOKEN
	{
      $$ := new Object_Qualifier_Token;
      Object_Qualifier_Token($$.all).Qualifier := (Aliased_Qualifier => True,
                                                   Constant_Qualifier => True);
   }
	;

object_subtype_def : subtype_ind
   {
      $$ := $1;
   }

	| array_type
	{
      $$ := $1;
   }
	;

init_opt :

   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Null_Unbounded_String;
   }

	| ASSIGNMENT expression
	{
      $$ := $2;
   }
	;

number_decl : def_id_s ':' CONSTANT_TOKEN ASSIGNMENT expression ';'
   {
      $$ := new Object_Declaration_Token;
      Object_Declaration_Token($$.all).Line_Number := Get_Current_Line;
      Object_Declaration_Token($$.all).Def_ID_S := Def_ID_S_Token_Ptr($1);
      Object_Declaration_Token($$.all).Qualifier :=
      new Object_Qualifier_Token'(Ada.Finalization.Controlled with
      Line_Number => 0,
      Qualifier =>
      (Aliased_Qualifier => False,
      Constant_Qualifier => True));
      Object_Declaration_Token($$.all).Subtype_Def := Null_Unbounded_String;
      Object_Declaration_Token($$.all).Init := Dummy_String_Token($5.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	;

type_decl : TYPE_TOKEN def_id discrim_part_opt type_completion ';'
   {
      if $4 /= null then
         Generic_Type_Token($4.all).Line_Number :=
         Dummy_String_Token($2.all).Line_Number;

         Generic_Type_Token($4.all).Name := Dummy_String_Token($2.all).Str;

         if $3 /= null then
            Generic_Discrimant_Type_Token($4.all).Discriminant_Part :=
            Discriminant_Token_Ptr($3);
         end if;

         if not In_Private then
            Insert(Tree, $4);
         else
            Insert(Private_Tree, $4);
         end if;
      end if;
   }
	;

discrim_part_opt :
   {
      $$ := null;
   }
	| discrim_part
	{
	   $$ := $1;
	}
	| '(' BOX ')'
	{
      $$ := new Discriminant_Token;
      Discriminant_Token($$.all).Def_ID_S := new Def_ID_S_Token'(
      Ada.Finalization.Controlled with 0, To_Unbounded_String("<>"), null);
      Discriminant_Token($$.all).Type_Def := Null_Unbounded_String;
      Discriminant_Token($$.all).Init := Null_Unbounded_String;
	}
	;

type_completion :
   {
      $$ := null;
   }
	| IS_TOKEN type_def
	{
	   $$ := $2;
	}
	;

type_def : enumeration_type
   {
	   $$ := new Simple_Type_Token;
	   Simple_Type_Token($$.all).Declaration_Part := Dummy_String_Token($1.all).Str;
	}
	| integer_type
	{
	   $$ := new Simple_Type_Token;
	   Simple_Type_Token($$.all).Declaration_Part := Dummy_String_Token($1.all).Str;
	}
	| real_type
	{
	   $$ := new Simple_Type_Token;
	   Simple_Type_Token($$.all).Declaration_Part := Dummy_String_Token($1.all).Str;
	}
	| array_type
	{
	   $$ := new Simple_Type_Token;
	   Simple_Type_Token($$.all).Declaration_Part := Dummy_String_Token($1.all).Str;
	}
	| record_type
	{
	   $$ := $1;
	}
	| access_type
	{
	   $$ := new Simple_Type_Token;
	   Simple_Type_Token($$.all).Declaration_Part := Dummy_String_Token($1.all).Str;
	}
	| derived_type
	{
	   $$ := $1;
	}
	| private_type
	{
	   $$ := $1;
	}
	;

subtype_decl : SUBTYPE_TOKEN simple_name IS_TOKEN subtype_ind ';'
   {
      $$ := new Subtype_Decl_Token;
      Subtype_Decl_Token($$.all).Name := Dummy_String_Token($2.all).Str;
      Subtype_Decl_Token($$.all).Declaration_Part := Dummy_String_Token($4.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	;

subtype_ind : name constraint
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ' ' &
                                        Dummy_String_Token($2.all).Str;
   }
	| name
	{
      $$ := $1;
   }
	;

constraint : range_constraint
   {
      $$ := $1;
   }
	| decimal_digits_constraint
	{
      $$ := $1;
   }
	;

decimal_digits_constraint : DIGITS_TOKEN expression range_constr_opt
	;

derived_type : NEW_TOKEN subtype_ind
   {
      $$ := new Simple_Type_Token;
      Simple_Type_Token($$.all).Declaration_Part := "new " &
      Dummy_String_Token($2.all).Str;
   }
	| NEW_TOKEN subtype_ind WITH_TOKEN PRIVATE_TOKEN
	{
      $$ := new Derived_Type_Token;
      Derived_Type_Token($$.all).Inheritance := Dummy_String_Token($2.all).Str;
      Derived_Type_Token($$.all).Declaration_Part := "new " &
      Dummy_String_Token($2.all).Str & " with private";
   }
	| NEW_TOKEN subtype_ind WITH_TOKEN record_def
	{
	   Record_Type_Token($4.all).Poo_Part := new Poo_Record_Token'
	   (Ada.Finalization.Controlled with
       0,
       Dummy_String_Token($2.all).Str,
       False,
       False);


	}
	| ABSTRACT_TOKEN NEW_TOKEN subtype_ind WITH_TOKEN PRIVATE_TOKEN
	{
      $$ := new Derived_Type_Token;
      Derived_Type_Token($$.all).Inheritance := Dummy_String_Token($3.all).Str;
      Derived_Type_Token($$.all).Declaration_Part := "abstract new " &
      Dummy_String_Token($3.all).Str & " with private";
   }
	| ABSTRACT_TOKEN NEW_TOKEN subtype_ind WITH_TOKEN record_def
   {
	   Record_Type_Token($5.all).Poo_Part := new Poo_Record_Token'(
	   Ada.Finalization.Controlled with
      0,
      Dummy_String_Token($3.all).Str,
      False,
      True);


	}
	;

range_constraint : RANGE_TOKEN range
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "range " &
                                        Dummy_String_Token($2.all).Str;
   }
	;

range : simple_expression DOUBLE_DOT simple_expression
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ".." &
                                        Dummy_String_Token($3.all).Str;
   }
	| name TIC RANGE_TOKEN
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ''' & "Range";

   }
	| name TIC RANGE_TOKEN '(' expression ')'
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ''' &
                                        "Range " &
                                        '(' & Dummy_String_Token($5.all).Str & ')';

   }
	;

enumeration_type : '(' enum_id_s ')'
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := '(' & Dummy_String_Token($2.all).Str & ')';
   }
   ;

enum_id_s : enum_id
   {
      $$ := $1;
   }
	| enum_id_s ',' enum_id
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ", " &
                                        Dummy_String_Token($3.all).Str;
   }
	;

enum_id : identifier
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String(Get_Token_Value);
   }
	| char_lit
	{
      $$ := $1;
   }
	;

integer_type : range_spec
   {
      $$ := $1;
   }
	| MOD_TOKEN expression
	{
	   $$ := new Dummy_String_Token;
	   Dummy_String_Token($$.all).Str := "mod " &
	                                     Dummy_String_Token($2.all).Str;
	}
	;


range_spec : range_constraint
   {
      $$ := $1;
   }
	;

range_spec_opt :
   {
      $$ := null;
   }
	| range_spec
	{
	   $$ := $1;
	}
	;

real_type : float_type
   {
      $$ := $1;
   }
	| fixed_type
	{
	   $$ := $1;
	}
	;

float_type : DIGITS_TOKEN expression range_spec_opt
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "digits " &
                                        Dummy_String_Token($2.all).Str;
      if $3 /= null then
         Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str & ' ' &
                                           Dummy_String_Token($3.all).Str;
      end if;
   }
	;

fixed_type : DELTA_TOKEN expression range_spec
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "delta " &
                                        Dummy_String_Token($2.all).Str & ' ' &
                                        Dummy_String_Token($3.all).Str;
   }
	| DELTA_TOKEN expression DIGITS_TOKEN expression range_spec_opt
	{
	   $$ := new Dummy_String_Token;
	   Dummy_String_Token($$.all).Str := "delta " &
                                        Dummy_String_Token($2.all).Str &
                                        " digits " &
                                        Dummy_String_Token($4.all).Str;

      if $5 /= null then
         Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str & ' ' &
                                           Dummy_String_Token($5.all).Str;
      end if;
   }
	;

array_type : unconstr_array_type
   {
      $$ := $1;
   }
	| constr_array_type
	{
      $$ := $1;
   }
	;

unconstr_array_type : ARRAY_TOKEN '(' index_s ')' OF_TOKEN component_subtype_def

   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "array (" &
                                        Dummy_String_Token($3.all).Str & ") of " &
                                        Dummy_String_Token($6.all).Str;

   }

	;

constr_array_type : ARRAY_TOKEN iter_index_constraint OF_TOKEN component_subtype_def

   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "array " &
                                        Dummy_String_Token($2.all).Str &
                                        " of " &
                                        Dummy_String_Token($4.all).Str;
   }
	;

component_subtype_def : aliased_opt subtype_ind
   {
      $$ := $1;
      if Dummy_String_Token($$.all).Str /= Null_Unbounded_String then
         Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str & ' ' &
                                           Dummy_String_Token($2.all).Str;
      else
         Dummy_String_Token($$.all).Str := Dummy_String_Token($2.all).Str;
      end if;
   }
	;

aliased_opt :
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Null_Unbounded_String;
   }
	| ALIASED_TOKEN
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("aliased");
   }
	;

index_s : index
	| index_s ',' index
	;

index : name RANGE_TOKEN BOX
	;

iter_index_constraint : '(' iter_discrete_range_s ')'
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := '(' & Dummy_String_Token($2.all).Str & ')';
   }
	;

iter_discrete_range_s : discrete_range
   {
      $$ := $1;
   }
	| iter_discrete_range_s ',' discrete_range
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ',' &
                                        Dummy_String_Token($3.all).Str;
    }
	;

discrete_range : name range_constr_opt
   {

      $$ := new Dummy_String_Token;

      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str;

      if Dummy_String_Token($2.all).Str /= Null_Unbounded_String then
         Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str & ' ' &
                                           Dummy_String_Token($2.all).Str;
      end if;
   }
	| range
	{
      $$ := $1;
   }
	;

range_constr_opt :
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Null_Unbounded_String;
   }
	| range_constraint
	{
	   $$ := $1;
	}
	;

record_type : tagged_opt limited_opt record_def
   {
      $$ := $3;
      Record_Type_Token($$.all).Poo_Part := Poo_Record_Token_Ptr($1);
   }
	;

record_def : RECORD_TOKEN pragma_s comp_list END_TOKEN RECORD_TOKEN
   {
      $$ := new Record_Type_Token;
      Record_Type_Token($$.all).Component_List := Component_List_Token_Ptr($3);
   }
	| NULL_TOKEN RECORD_TOKEN
	{
	   $$ := new Record_Type_Token;
      Record_Type_Token($$.all).Null_Record := True;
	}
	;

tagged_opt :
   {
      $$ := null;
   }
	| TAGGED_TOKEN
	{
	   $$ := new Poo_Record_Token;
	}
	| ABSTRACT_TOKEN TAGGED_TOKEN
	{
	   $$ := new Poo_Record_Token;
	   Poo_Record_Token($$.all).Is_Abstract := True;
	}
	;


comp_list : comp_decl_s variant_part_opt
   {
      $$ := new Component_List_Token;
      Component_List_Token($$.all).Component_Part := Component_Token_Ptr($1);
      Component_List_Token($$.all).Variant_Part := Variant_Token_Ptr($2);
   }
	| variant_part pragma_s
	{
	   $$ := new Component_List_Token;
      Component_List_Token($$.all).Variant_Part := Variant_Token_Ptr($1);
	}
	| NULL_TOKEN ';' pragma_s
	{
	   $$ := null;
	}
	;

comp_list_variant : comp_decl_s variant_part_opt
   {
      $$ := new Component_List_Token;
      Component_List_Token($$.all).Component_Part := Component_Token_Ptr($1);
      Component_List_Token($$.all).Variant_Part := Variant_Token_Ptr($2);
   }
	| variant_part pragma_s
	{
	   $$ := new Component_List_Token;
      Component_List_Token($$.all).Variant_Part := Variant_Token_Ptr($1);
	}
	| NULL_TOKEN ';' pragma_s
	{
	   $$ := null;
	}
	;

comp_decl_s : comp_decl
   {
      $$ := $1;
   }
	| comp_decl_s pragma_s comp_decl
	{
	   $$ := $3;
	   Component_Token($$.all).Next_Component := Component_Token_Ptr($1);
	}
	;

variant_part_opt : pragma_s
   {
      $$ := null;
   }
	| pragma_s variant_part pragma_s
	{
	   $$ := $2;
	}
	;

comp_decl : def_id_s ':' component_subtype_def init_opt ';'
   {
      $$ := new Component_Token;
      Component_Token($$.all).Line_Number := Get_Current_Line;
      Component_Token($$.all).Def_ID_S := Def_ID_S_Token_Ptr($1);
      Component_Token($$.all).Type_Def := Dummy_String_Token($3.all).Str;
      Component_Token($$.all).Init := Dummy_String_Token($4.all).Str;
   }
	| error ';'
	;

discrim_part : '(' discrim_spec_s ')'
   {
      $$ := $2;
   }
	;

discrim_spec_s : discrim_spec
   {
      $$ := $1;
   }
	| discrim_spec_s ';' discrim_spec
	{
	   $$ := new Discriminant_Token;
	   Discriminant_Token($$.all) := Discriminant_Token($3.all);
	   Discriminant_Token($$.all).Next_Component := Component_Token_Ptr($1);
	}
	;

discrim_spec : def_id_s ':' access_opt mark init_opt
   {
      $$ := new Discriminant_Token;
      Discriminant_Token($$.all).Line_Number := Get_Current_Line;
      Discriminant_Token($$.all).Def_ID_S := Def_ID_S_Token_Ptr($1);
      Discriminant_Token($$.all).Type_Def := Dummy_String_Token($3.all).Str & ' ' &
                                             Dummy_String_Token($4.all).Str;
      Discriminant_Token($$.all).Init :=  Dummy_String_Token($5.all).Str;
   }
	| error
	;

access_opt :
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Null_Unbounded_String;
   }
	| ACCESS_TOKEN
	{
	   $$ := new Dummy_String_Token;
	   Dummy_String_Token($$.all).Str := To_Unbounded_String("access");
	}
	;

variant_part : CASE_TOKEN simple_name IS_TOKEN pragma_s variant_s END_TOKEN CASE_TOKEN ';'
   {
      $$ := new Variant_Token;
      Variant_Token($$.all).Discriminant := Dummy_String_Token($2.all).Str;
      Variant_Token($$.all).Choice := Variant_Choice_Token_Ptr($5);
   }
	;

variant_s : variant
   {
      $$ := $1;
   }
	|  variant variant_s
	{
	   $$ := $1;
	   Variant_Choice_Token($$.all).Next_Variant_Choice := Variant_Choice_Token_Ptr($2);
	}
	;

variant : WHEN_TOKEN choice_s ARROW pragma_s comp_list_variant
   {
      $$ := new Variant_Choice_Token;
      Variant_Choice_Token($$.all).Line_Number := Get_Current_Line;
      Variant_Choice_Token($$.all).Choice := Dummy_String_Token($2.all).Str;
      Variant_Choice_Token($$.all).Component_List := Component_List_Token_Ptr($5);
   }
	;

choice_s : choice
   {
      $$ := $1;
   }
	| choice_s '|' choice
	{
	   $$ := $3;
	   Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & " | " &
	                                     Dummy_String_Token($$.all).Str;
	}
	;

choice : expression
   {
      $$ := $1;
   }
	| discrete_with_range
	{
	   $$ := $1;
	}
	| OTHERS_TOKEN
	{
	   $$ := new Dummy_String_Token;
	   Dummy_String_Token($$.all).Str := To_Unbounded_String("others");
	}
	;

discrete_with_range : name range_constraint
	| range
	;

access_type : ACCESS_TOKEN subtype_ind
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "access " &
                                        Dummy_String_Token($2.all).Str;
   }
	| ACCESS_TOKEN CONSTANT_TOKEN subtype_ind
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "access constant " &
                                        Dummy_String_Token($3.all).Str;
   }
	| ACCESS_TOKEN ALL_TOKEN subtype_ind
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "access all " &
                                        Dummy_String_Token($3.all).Str;
   }
	| ACCESS_TOKEN prot_opt PROCEDURE_TOKEN formal_part_opt
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("access ");

      if $2 /= null then
         Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str &
                                           Dummy_String_Token($2.all).Str & ' ';
      end if;

      Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str &
                                        "procedure";
      if $4 /= null then
         Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str & ' ' &
                                           Concat(Parameters_Token_Ptr($4).all);
      end if;
   }
	| ACCESS_TOKEN prot_opt FUNCTION_TOKEN formal_part_opt RETURN_TOKEN mark
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("access ");

      if $2 /= null then
         Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str &
                                           Dummy_String_Token($2.all).Str & ' ';
      end if;

      Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str &
                                        "function";
      if $4 /= null then
         Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str & ' ' &
                                           Concat(Parameters_Token_Ptr($4).all) & ' ';
      end if;

      Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str &
                                        "return " & Dummy_String_Token($6.all).Str;
   }
	;

prot_opt :
   {
      $$ := null;
   }
	| PROTECTED_TOKEN
	{
	   $$ := new Dummy_String_Token;
	   Dummy_String_Token($$.all).Str := To_Unbounded_String("protected");
	}
	;

decl_part :
	| decl_item_or_body_s1
	;

decl_item_s :
	| decl_item_s1
	;

decl_item_s1 : decl_item
	| decl_item_s1 decl_item
	;

decl_item : decl
	| use_clause
	| rep_spec
	| pragma
	;

decl_item_or_body_s1 : decl_item_or_body
	| decl_item_or_body_s1 decl_item_or_body
	;

decl_item_or_body : body
	| decl_item
	;

body : subprog_body
	| pkg_body
	| task_body
	| prot_body
	;

name : simple_name
   {
      $$ := $1;
   }

	| indexed_comp
	{
	   $$ := $1;
	}
	| selected_comp
	{
	   $$ := $1;
	}
	| attribute
	{
	   $$ := $1;
	}
	| operator_symbol
	{
      $$ := $1;
   }
	;

mark : simple_name
   {
      $$ := $1;
   }
	| mark TIC attribute_id
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ''' &
                                        Dummy_String_Token($3.all).Str;
   }
	| mark '.' simple_name
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & '.' &
                                        Dummy_String_Token($3.all).Str;
   }
	;

simple_name : identifier
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Line_Number := Get_Current_Line;
      Dummy_String_Token($$.all).Str := To_Unbounded_String(Get_Token_Value);
   }
	;

compound_name : simple_name
   {
      $$ := $1;
   }
	| compound_name '.' simple_name
	{
     $$ := $3;
     Dummy_String_Token($$.all).Line_Number := Get_Current_Line;
     Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & '.' &
     Dummy_String_Token($$.all).Str;
   }
	;

c_name_list : compound_name
   {
      $$ := new Def_ID_S_Token;
      Def_ID_S_Token($$.all).Str := Dummy_String_Token($1.all).Str;
   }
	 | c_name_list ',' compound_name
	{
	   $$ := new Def_ID_S_Token;
      Def_ID_S_Token($$.all).Next_ID := Def_ID_S_Token_Ptr($1);
      Def_ID_S_Token($$.all).Str := Dummy_String_Token($3.all).Str;
	}
	;

used_char : char_lit
	;

operator_symbol : char_string
   {
      $$ := $1;
   }
	;

indexed_comp : name '(' value_s ')'
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & " (" &
                                        Dummy_String_Token($3.all).Str & ')';
   }
	;

value_s : value
   {
     $$ := $1;
   }
	| value_s ',' value
	{
	  $$ := new Dummy_String_Token;
     Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ", "
                                       & Dummy_String_Token($3.all).Str;
   }
	;

value : expression
   {
     $$ := $1;
   }
	| comp_assoc
	{
     $$ := $1;
   }
	| discrete_with_range
	{
     $$ := $1;
   }
	| error
	;

selected_comp : name '.' simple_name
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & '.' &
                                        Dummy_String_Token($3.all).Str;
   }
	| name '.' used_char
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & '.' &
                                        Dummy_String_Token($3.all).Str;
   }
	| name '.' operator_symbol
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & '.' &
                                        Dummy_String_Token($3.all).Str;
   }
	| name '.' ALL_TOKEN
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ".all";
   }
	;

attribute : name TIC attribute_id
   {
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ''' &
                                        Dummy_String_Token($3.all).Str;
	}
	;

attribute_id : identifier
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String(Get_Token_Value);
   }
	| DIGITS_TOKEN
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("digits");
   }
	| DELTA_TOKEN
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("delta");
   }
	| ACCESS_TOKEN
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("access");
   }
	;

literal : numeric_lit
   {
      $$ := $1;
   }
	| used_char
	{
      $$ := $1;
   }
	| NULL_TOKEN
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("null");
   }
	;

aggregate : '(' comp_assoc ')'
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := '(' & Dummy_String_Token($2.all).Str & ')';
   }
	| '(' value_s_2 ')'
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := '(' & Dummy_String_Token($2.all).Str & ')';
   }
	| '(' expression WITH_TOKEN value_s ')'
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := '(' & Dummy_String_Token($2.all).Str & " with " &
                                        Dummy_String_Token($4.all).Str & ')';
   }
	| '(' expression WITH_TOKEN NULL_TOKEN RECORD_TOKEN ')'
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := '(' & Dummy_String_Token($2.all).Str &
                                        " with null record)";

   }
	| '(' NULL_TOKEN RECORD_TOKEN ')'
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("(with null record)");

   }
	;

value_s_2 : value ',' value
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str :=  Dummy_String_Token($1.all).Str & ", " &
                                         Dummy_String_Token($3.all).Str;
   }
	| value_s_2 ',' value
	{
	   $$ := new Dummy_String_Token;
	   Dummy_String_Token($$.all).Str :=  Dummy_String_Token($1.all).Str & ", " &
                                         Dummy_String_Token($3.all).Str;
	}
	;

comp_assoc : choice_s ARROW expression
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & " => " &
                                        Dummy_String_Token($3.all).Str;

   }
	;

expression : relation
   {
      $$ := $1;
   }
	| expression logical relation
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ' ' &
                                        Dummy_String_Token($2.all).Str & ' ' &
                                        Dummy_String_Token($3.all).Str;
   }
	| expression short_circuit relation
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ' ' &
                                        Dummy_String_Token($2.all).Str & ' ' &
                                        Dummy_String_Token($3.all).Str;
   }
	;

logical : AND_TOKEN
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("and");
   }
	| OR_TOKEN
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("or");
   }
	| XOR_TOKEN
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("xor");
   }
	;

short_circuit : AND_TOKEN THEN_TOKEN

   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("and then");
   }
	| OR_TOKEN ELSE_TOKEN
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("or else");
   }
	;

relation : simple_expression
   {
      $$ := $1;
   }
	| simple_expression relational simple_expression
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str
                                        & Dummy_String_Token($2.all).Str
                                        & Dummy_String_Token($3.all).Str;
   }
	| simple_expression membership range
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str
                                        & Dummy_String_Token($2.all).Str
                                        & Dummy_String_Token($3.all).Str;
   }
	| simple_expression membership name
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str
                                        & Dummy_String_Token($2.all).Str
                                        & Dummy_String_Token($3.all).Str;
   }
	;

relational : '='
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("=");
   }
	| NE
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String(Get_Token_Value);
   }
	| '<'
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("<");
   }
	| LT_EQ
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String(Get_Token_Value);
   }
	| '>'
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String(">");
   }
	| GE
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String(Get_Token_Value);
   }
	;

membership : IN_TOKEN
   {
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("in");
   }
	| NOT_TOKEN IN_TOKEN
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("not in");
   }
	;

simple_expression : unary term
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str &
                                        Dummy_String_Token($2.all).Str;
   }
	| term
	{
      $$ := $1;

   }
	| simple_expression adding term
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ' ' &
                                        Dummy_String_Token($2.all).Str & ' ' &
                                        Dummy_String_Token($3.all).Str;
   }
	;

unary   : '+'
   {
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("+");
   }
	| '-'
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("-");
   }
	;

adding  : '+'
   {
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("+");
   }
	| '-'
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("-");
   }
	| '&'
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("&");
   }
	;

term    : factor
   {
	   $$ := $1;
   }
	| term multiplying factor
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ' ' &
                                        Dummy_String_Token($2.all).Str & ' ' &
                                        Dummy_String_Token($3.all).Str;
   }
	;

multiplying : '*'
   {
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("*");
   }
	| '/'
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("/");
   }
	| MOD_TOKEN
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("mod");
   }
	| REM_TOKEN
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("rem");
   }
	;

factor : primary
   {
	   $$ := $1;
   }
	| NOT_TOKEN primary
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "not " & Dummy_String_Token($2.all).Str;
   }
	| ABS_TOKEN primary
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "abs " & Dummy_String_Token($2.all).Str;
   }
	| primary DOUBLE_STAR primary
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ' ' &
                                        " ** " &
                                        Dummy_String_Token($3.all).Str;
   }
	;

primary : literal
   {
	   $$ := $1;
   }
	| name
	{
	   $$ := $1;
   }
	| allocator
	{
	   $$ := $1;
   }
	| qualified
	{
	   $$ := $1;
   }
	| parenthesized_primary
	{
	   $$ := $1;
   }
	;

parenthesized_primary : aggregate
   {
	   $$ := $1;
   }
	| '(' expression ')'
	{
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := '(' & Dummy_String_Token($2.all).Str & ')';
   }
	;

qualified : name TIC parenthesized_primary
   {
	   $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($1.all).Str & ''' &
      Dummy_String_Token($3.all).Str;
   }
	;

allocator : NEW_TOKEN name
	| NEW_TOKEN qualified
	;

statement_s : statement
	| statement_s statement
	;

statement : unlabeled
	| label statement
	;

unlabeled : simple_stmt
	| compound_stmt
	| pragma
	;

simple_stmt : null_stmt
	| assign_stmt
	| exit_stmt
	| return_stmt
	| goto_stmt
	| procedure_call
	| delay_stmt
	| abort_stmt
	| raise_stmt
	| code_stmt
	| requeue_stmt
	| error ';'
	;

compound_stmt : if_stmt
	| case_stmt
	| loop_stmt
	| block
	| accept_stmt
	| select_stmt
	;

label : LT_LT identifier GT_GT
	;

null_stmt : NULL_TOKEN ';'
	;

assign_stmt : name ASSIGNMENT expression ';'
	;

if_stmt : IF_TOKEN cond_clause_s else_opt END_TOKEN IF_TOKEN ';'
	;

cond_clause_s : cond_clause
	| cond_clause_s ELSIF_TOKEN cond_clause
	;

cond_clause : cond_part statement_s
	;

cond_part : condition THEN_TOKEN
	;

condition : expression
	;

else_opt :
	| ELSE_TOKEN statement_s
	;

case_stmt : case_hdr pragma_s alternative_s END_TOKEN CASE_TOKEN ';'
	;

case_hdr : CASE_TOKEN expression IS_TOKEN
	;

alternative_s :
	| alternative_s alternative
	;

alternative : WHEN_TOKEN choice_s ARROW statement_s
	;

loop_stmt : label_opt iteration basic_loop id_opt ';'
	;

label_opt :
	| identifier ':'
	;

iteration :
	| WHILE_TOKEN condition
	| iter_part reverse_opt discrete_range
	;

iter_part : FOR_TOKEN identifier IN_TOKEN
	;

reverse_opt :
	| REVERSE_TOKEN
	;

basic_loop : LOOP_TOKEN statement_s END_TOKEN LOOP_TOKEN
	;

id_opt :
	| designator
	;

block : label_opt block_decl block_body END_TOKEN id_opt ';'
	;

block_decl :
	| DECLARE_TOKEN decl_part
	;

block_body : BEGIN_TOKEN handled_stmt_s
	;

handled_stmt_s : statement_s except_handler_part_opt
	;

except_handler_part_opt :
	| except_handler_part
	;

exit_stmt : EXIT_TOKEN name_opt when_opt ';'
	;

name_opt :
	| name
	;

when_opt :
	| WHEN_TOKEN condition
	;

return_stmt : RETURN_TOKEN ';'
	| RETURN_TOKEN expression ';'
	;

goto_stmt : GOTO_TOKEN name ';'
	;

subprog_decl : subprog_spec ';'
   {
      $$ := $1;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	| generic_subp_inst ';'
	| subprog_spec_is_push ABSTRACT_TOKEN ';'
	{
	   Subprog_Token($1.all).Is_Abstract := True;

	   if not In_Private then
         Insert(Tree, $1);
      else
         Insert(Private_Tree, $1);
      end if;
	}
	;

subp_name : compound_name
   {
      Dummy_String_Token($1.all).Line_Number := Get_Current_Line;
      $$ := $1;
   };

subprog_spec : PROCEDURE_TOKEN subp_name formal_part_opt
   {
      $$ := new Procedure_Decl_Token;
      Procedure_Decl_Token($$.all).Line_Number := Dummy_String_Token($2.all).Line_Number;
      Procedure_Decl_Token($$.all).Name := Dummy_String_Token($2.all).Str;
      Procedure_Decl_Token($$.all).Parameters := Parameters_Token_Ptr($3);
   }
	| FUNCTION_TOKEN designator formal_part_opt RETURN_TOKEN name
	{
	   $$ := new Function_Decl_Token;
      Function_Decl_Token($$.all).Line_Number := Dummy_String_Token($2.all).Line_Number;
      Function_Decl_Token($$.all).Name := Dummy_String_Token($2.all).Str;
      Function_Decl_Token($$.all).Parameters := Parameters_Token_Ptr($3);
      Function_Decl_Token($$.all).Return_Type := Dummy_String_Token($5.all).Str;
	}
	| FUNCTION_TOKEN designator --  for generic inst and generic rename
	{
	   $$ := new Function_Decl_Token;
      Function_Decl_Token($$.all).Line_Number := Dummy_String_Token($2.all).Line_Number;
      Function_Decl_Token($$.all).Name := Dummy_String_Token($2.all).Str;
   }
	;

designator : subp_name
   {
      Dummy_String_Token($1.all).Line_Number := Get_Current_Line;
      $$ := $1;
   }
	| char_string
	{
	   Dummy_String_Token($1.all).Line_Number := Get_Current_Line;
	   $$ := $1;
	}
	;

formal_part_opt :
   {
      --No parameters return a null pointer
      $$ := null;
   }
	| formal_part
	{
	   $$ := $1;
	}
	;

formal_part : '(' param_s ')'
   {
	   $$ := $2;
	}
	;

param_s : param
   {
	   $$ := $1;
	}
	| param ';' param_s
   {
     --Chain the parameters
	  $$ := $1;
	  Parameters_Token($$.all).Next := Parameters_Token_Ptr($3);
	}
	;

param : def_id_s ':' mode mark init_opt
   {
      $$ := new Parameters_Token;
      Parameters_Token($$.all).Line_Number := Get_Current_Line;
      Parameters_Token($$.all).Def_ID_S := Def_ID_S_Token_Ptr($1);
      Parameters_Token($$.all).Mode := Mode_Token_Ptr($3);
      Parameters_Token($$.all).Type_Param := Dummy_String_Token($4.all).Str;
      Parameters_Token($$.all).Init := Dummy_String_Token($5.all).Str;
   }
	| error
	;

mode :
   {
	   $$ := new Mode_Token;
	   Mode_Token($$.all).Mode := In_Mode;
	}
	| IN_TOKEN
	{
	   $$ := new Mode_Token;
	   Mode_Token($$.all).Mode := In_Mode;
	}
	| OUT_TOKEN
	{
	   $$ := new Mode_Token;
	   Mode_Token($$.all).Mode := Out_Mode;
	}
	| IN_TOKEN OUT_TOKEN
	{
	   $$ := new Mode_Token;
	   Mode_Token($$.all).Mode := In_Out_Mode;
	}
	| ACCESS_TOKEN
	{
	   $$ := new Mode_Token;
	   Mode_Token($$.all).Mode := Access_Mode;
	}
	;

subprog_spec_is_push : subprog_spec IS_TOKEN
   {
      $$ := $1;
   }
	;

subprog_body : subprog_spec_is_push
	       decl_part block_body END_TOKEN id_opt ';'
	;

procedure_call : name ';'
	;

pkg_decl : pkg_spec ';'
	| generic_pkg_inst ';'
	;

pkg_spec : PACKAGE_TOKEN compound_name IS_TOKEN decl_item_s
           private_part END_TOKEN c_id_opt
   {
      $$ := new Package_Spec_Token;
      Package_Spec_Token($$.all).Name := Dummy_String_Token($2.all).Str;

      Insert(Tree, $$);
   }
   ;
private_part :
	| private_rule decl_item_s
	;

private_rule : PRIVATE_TOKEN
   {
      --We are in the private part of the package turn the flag
	   In_Private := True;
	};

c_id_opt :
	| compound_name
	;

pkg_body : PACKAGE_TOKEN BODY_TOKEN compound_name IS_TOKEN
	       decl_part body_opt END_TOKEN c_id_opt ';'
	;

body_opt :
	| block_body
	;

private_type : tagged_opt limited_opt PRIVATE_TOKEN
   {
      $$ := new Simple_Type_Token;

      if $1 = null then
         Simple_Type_Token($$.all).Declaration_Part :=
         Dummy_String_Token($2.all).Str & " private";
      else
         if Poo_Record_Token($1.all).Is_Abstract then
            Simple_Type_Token($$.all).Declaration_Part :=
            To_Unbounded_String("abstract tagged");
         else
            Simple_Type_Token($$.all).Declaration_Part :=
            To_Unbounded_String("tagged");
         end if;
         Simple_Type_Token($$.all).Declaration_Part :=
         Simple_Type_Token($$.all).Declaration_Part & ' ' &
         Dummy_String_Token($2.all).Str & " private";
      end if;
   }
	;


limited_opt :
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Null_Unbounded_String;
   }
	| LIMITED_TOKEN
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("limited");
   }
	;

use_clause : USE_TOKEN name_s ';'
   {
      $$ := new Use_Clause_Token;
      Use_Clause_Token($$.all).Line_Number := Get_Current_Line;
      Use_Clause_Token($$.all).Name_S := Def_ID_S_Token_Ptr($2);

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	| USE_TOKEN TYPE_TOKEN name_s ';'
	{
      $$ := new Use_Type_Clause_Token;
      Use_Type_Clause_Token($$.all).Line_Number := Get_Current_Line;
      Use_Type_Clause_Token($$.all).Name_S := Def_ID_S_Token_Ptr($3);

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	;

name_s : name
   {
      $$ := new Def_ID_S_Token;
      Def_ID_S_Token($$.all).Line_Number := Get_Current_Line;
      Def_ID_S_Token($$.all).Str := Dummy_String_Token($1.all).Str;
   }
	| name_s ',' name
	{
      $$ := new Def_ID_S_Token;
      Def_ID_S_Token($$.all).Line_Number := Get_Current_Line;
      Def_ID_S_Token($$.all).Next_ID := Def_ID_S_Token_Ptr($1);
      Def_ID_S_Token($$.all).Str := Dummy_String_Token($3.all).Str;
   }
	;

rename_decl : def_id_s ':' object_qualifier_opt subtype_ind renames ';'
   {
      $$ := new Renames_Object_Token;
      Renames_Object_Token($$.all).Line_Number := Def_ID_S_Token($1.all).Line_Number;
      Renames_Object_Token($$.all).Def_Id_S := Def_ID_S_Token_Ptr($1);
      Renames_Object_Token($$.all).Qualifier := Object_Qualifier_Token_Ptr($3);
      Renames_Object_Token($$.all).Subtype_Ind := Dummy_String_Token($4.all).Str;
      Renames_Object_Token($$.all).Rename := Dummy_String_Token($5.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;

   }
	| def_id_s ':' EXCEPTION_TOKEN renames ';'
	{
	   $$ := new Renames_Exception_Token;
	   Renames_Exception_Token($$.all).Line_Number := Def_ID_S_Token($1.all).Line_Number;
	   Renames_Exception_Token($$.all).Def_Id_S := Def_ID_S_Token_Ptr($1);
	   Renames_Exception_Token($$.all).Rename := Dummy_String_Token($4.all).Str;

	   if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;

	}
	| rename_unit
	;

rename_unit : PACKAGE_TOKEN compound_name renames ';'
   {
      $$ := new Renames_Package_Token;
      Renames_Package_Token($$.all).Line_Number :=
      Dummy_String_Token($2.all).Line_Number;
      Renames_Package_Token($$.all).Name := Dummy_String_Token($2.all).Str;
      Renames_Package_Token($$.all).Rename := Dummy_String_Token($3.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	| subprog_spec renames ';'
	{
      $$ := new Renames_Subp_Token;
      Renames_Subp_Token($$.all).Line_Number := Subprog_Token($1.all).Line_Number;
      Renames_Subp_Token($$.all).Subprog_Spec := Subprog_Token_Ptr($1);
      Renames_Subp_Token($$.all).Rename := Dummy_String_Token($2.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;

	}
	| generic_formal_part PACKAGE_TOKEN compound_name renames ';'
	{
	   $$ := new Renames_Generic_Package_Token;
	   Renames_Generic_Package_Token($$.all).Line_Number :=
      Dummy_String_Token($3.all).Line_Number;
	   Renames_Generic_Package_Token($$.all).Name := Dummy_String_Token($3.all).Str;
      Renames_Generic_Package_Token($$.all).Rename := Dummy_String_Token($4.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
	}
	| generic_formal_part subprog_spec renames ';'
	{
      $$ := new Renames_Generic_Subp_Token;
      Renames_Generic_Subp_Token($$.all).Line_Number := Subprog_Token($2.all).Line_Number;
      Renames_Generic_Subp_Token($$.all).Subprog_Spec := Subprog_Token_Ptr($2);
      Renames_Generic_Subp_Token($$.all).Rename := Dummy_String_Token($2.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;

	}
	;

renames : RENAMES_TOKEN name
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($2.all).Str;
   }
	;

task_decl : task_spec ';'
	;

task_spec : TASK_TOKEN simple_name task_def
   {
      Task_Decl_Token($3.all).Line_Number:= Dummy_String_Token($2.all).Line_Number;
      Task_Decl_Token($3.all).Name := Dummy_String_Token($2.all).Str;

      if not In_Private then
         Insert(Tree, $3);
      else
         Insert(Private_Tree, $3);
      end if;

   }
	| TASK_TOKEN TYPE_TOKEN simple_name discrim_part_opt task_def
	{
     $$ := new Task_Type_Decl_Token'(Task_Decl_Token($5.all) with null record);
	  Task_Type_Decl_Token($$.all).Line_Number := Dummy_String_Token($3.all).Line_Number;
     Task_Type_Decl_Token($$.all).Name := Dummy_String_Token($3.all).Str;
     Task_Type_Decl_Token($$.all).Discriminant := Discriminant_Token_Ptr($4);

	  if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
     end if;
	}
	;

task_def :
   {
	   $$ := new Task_Decl_Token;
	}
	| IS_TOKEN entry_decl_s rep_spec_s task_private_opt END_TOKEN id_opt
	{
	   $$ := new Task_Decl_Token;
	   Task_Decl_Token($$.all).Entries := Entry_Decl_List_Ptr($2);
	   Task_Decl_Token($$.all).Private_Entries := Entry_Decl_List_Ptr($4);
	}
	;

task_private_opt :
   {
      $$ := null;
   }
	| PRIVATE_TOKEN entry_decl_s rep_spec_s
	{
	   $$ := $2;
	}
	;

task_body : TASK_TOKEN BODY_TOKEN simple_name IS_TOKEN
	       decl_part block_body END_TOKEN id_opt ';'
	;

prot_decl : prot_spec ';'
	;

prot_spec : PROTECTED_TOKEN simple_name prot_def
   {

      Protected_Decl_Token($3.all).Line_Number := Dummy_String_Token($2.all).Line_Number;
      Protected_Decl_Token($3.all).Name := Dummy_String_Token($2.all).Str;

      if not In_Private then
         Insert(Tree, $3);
      else
         Insert(Private_Tree, $3);
      end if;

   }
	| PROTECTED_TOKEN TYPE_TOKEN simple_name discrim_part_opt prot_def
	{
      $$ := new Protected_Type_Decl_Token'(Protected_Decl_Token($5.all) with null record);

	   Protected_Type_Decl_Token($$.all).Line_Number :=
	   Dummy_String_Token($3.all).Line_Number;
      Protected_Type_Decl_Token($$.all).Name := Dummy_String_Token($3.all).Str;
      Protected_Type_Decl_Token($$.all).Discriminant := Discriminant_Token_Ptr($4);

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;

	}
	;

prot_def : IS_TOKEN prot_op_decl_s prot_private_opt END_TOKEN id_opt
   {
      $$ := new Protected_Decl_Token;
      Protected_Decl_Token($$.all).Prot_Op := Protected_Object_List_Ptr($2);
      Protected_Decl_Token($$.all).Prot_Op_Private :=
      Protected_Private_Object_List_Ptr($3);

   }
	;

prot_private_opt :
   {
      $$ := null;
   }
	| PRIVATE_TOKEN prot_elem_decl_s
	{
	   $$ := $2;
	}
   ;

prot_op_decl_s :
   {
      $$ := null;
   }
	| prot_op_decl_s prot_op_decl
	{
	   $$ := new Protected_Object_List;
	   Protected_Object_List($$.all).Item := Subprog_Token_Ptr($2);
	   Protected_Object_List($$.all).Next := Protected_Object_List_Ptr($1);
	}
	;

prot_op_decl : entry_decl
   {
      $$ := $1;
   }
	| subprog_spec ';'
	{
	   $$ := $1;
	}
	| rep_spec
	| pragma
	;

prot_elem_decl_s :
   {
      $$ := null;
   }
	| prot_elem_decl_s prot_elem_decl
	{
	   $$ := $2;
	   Protected_Private_Object_List($$.all).Next := Protected_Object_List_Ptr($1);

	}
	;

prot_elem_decl : prot_op_decl
   {

      $$ := new Protected_Private_Object_List;
      Protected_Private_Object_List($$.all).Item := Subprog_Token_Ptr($1);
   }
                 | comp_decl
   {

      $$ := new Protected_Private_Object_List;
      Protected_Private_Object_List($$.all).Private_Comp := Component_Token_Ptr($1);
   };

prot_body : PROTECTED_TOKEN BODY_TOKEN simple_name IS_TOKEN
	       prot_op_body_s END_TOKEN id_opt ';'
	;

prot_op_body_s : pragma_s
	| prot_op_body_s prot_op_body pragma_s
	;

prot_op_body : entry_body
	| subprog_body
	| subprog_spec ';'
	;

entry_decl_s :
       pragma_s
   {
      $$ := null;
   }
	|   entry_decl_s entry_decl pragma_s
	{
	   $$ := new Entry_Decl_List'(Entry_Decl_Token($2.all)
	         with next => Entry_Decl_List_Ptr($1));
	}
	;


entry_decl : ENTRY_TOKEN simple_name formal_part_opt ';'
   {
      $$ := new Entry_Decl_Token;
      Entry_Decl_Token($$.all).Line_Number := Get_Current_Line;
      Entry_Decl_Token($$.all).Name := Dummy_String_Token($2.all).Str;
      Entry_Decl_Token($$.all).Parameters := Parameters_Token_Ptr($3);


   }
   --!!BUG!! If we have this rule the parse read two tokens forward and the information
   --        we receive by the lexer are false!! It's du of the '(' discrete_range ')'
   --        and the formal parameters '('...')'. The parser need to read 2 tokens forward
   --        which one of this rule it have.
   --!!BUG!!
	--| ENTRY_TOKEN simple_name '(' discrete_range ')' formal_part_opt ';'
	--{

	--   $$ := new Entry_Decl_Token;
	--   Entry_Decl_Token($$.all).Line_Number := Get_Current_Line;
   --   Entry_Decl_Token($$.all).Name := Dummy_String_Token($2.all).Str;
   --   Entry_Decl_Token($$.all).Family := Dummy_String_Token($4.all).Str;
   --   Entry_Decl_Token($$.all).Parameters := Parameters_Token_Ptr($6);
	--}
	;

entry_body : ENTRY_TOKEN identifier formal_part_opt WHEN_TOKEN
                condition entry_body_part
	| ENTRY_TOKEN identifier '(' iter_part discrete_range ')'
		formal_part_opt WHEN_TOKEN condition entry_body_part
	;

entry_body_part : ';'
	| IS_TOKEN decl_part block_body END_TOKEN id_opt ';'
	;

rep_spec_s :
	| rep_spec_s rep_spec pragma_s
	;

entry_call : procedure_call
	;

accept_stmt : accept_hdr ';'
	| accept_hdr DO_TOKEN handled_stmt_s END_TOKEN id_opt ';'
	;

accept_hdr : ACCEPT_TOKEN entry_name formal_part_opt
	;

entry_name : simple_name
	| entry_name '(' expression ')'
	;

delay_stmt : DELAY_TOKEN expression ';'
	| DELAY_TOKEN UNTIL_TOKEN expression ';'
	;

select_stmt : select_wait
	| async_select
	| timed_entry_call
	| cond_entry_call
	;

select_wait : SELECT_TOKEN guarded_select_alt or_select else_opt
	      END_TOKEN SELECT_TOKEN ';'
	;

guarded_select_alt : select_alt
	| WHEN_TOKEN condition ARROW select_alt
	;

or_select :
	| or_select OR_TOKEN guarded_select_alt
	;

select_alt : accept_stmt stmts_opt
	| delay_stmt stmts_opt
	| TERMINATE_TOKEN ';'
	;

delay_or_entry_alt : delay_stmt stmts_opt
	| entry_call stmts_opt
        ;

async_select : SELECT_TOKEN delay_or_entry_alt
	       THEN_TOKEN ABORT_TOKEN statement_s
	       END_TOKEN SELECT_TOKEN ';'
	;

timed_entry_call : SELECT_TOKEN entry_call stmts_opt
		   OR_TOKEN delay_stmt stmts_opt
	           END_TOKEN SELECT_TOKEN ';'
	;

cond_entry_call : SELECT_TOKEN entry_call stmts_opt
		  ELSE_TOKEN statement_s
	          END_TOKEN SELECT_TOKEN ';'
	;

stmts_opt :
	| statement_s
	;

abort_stmt : ABORT_TOKEN name_s ';'
	;

compilation :
	| compilation comp_unit
	| pragma pragma_s
	;

comp_unit : context_spec private_opt unit pragma_s
	| private_opt unit pragma_s
	;

private_opt :
	| PRIVATE_TOKEN
	;

context_spec : with_clause use_clause_opt
	| context_spec with_clause use_clause_opt
	| context_spec pragma
	;

with_clause : WITH_TOKEN c_name_list ';'
   {
      $$ := new With_Clause_Token;
      With_Clause_Token($$.all).Line_Number := Get_Current_Line;
      With_Clause_Token($$.all).Name_S := Def_ID_S_Token_Ptr($2);

      Insert(Tree, $$);
   }
	;

use_clause_opt :
	| use_clause_opt use_clause
	;

unit : pkg_decl
	| pkg_body
	| subprog_decl
	| subprog_body
	| subunit
	| generic_decl
	| rename_unit
	;

subunit : SEPARATE_TOKEN '(' compound_name ')'
	      subunit_body
	;

subunit_body : subprog_body
	| pkg_body
	| task_body
	| prot_body
	;

body_stub : TASK_TOKEN BODY_TOKEN simple_name IS_TOKEN SEPARATE_TOKEN ';'
	| PACKAGE_TOKEN BODY_TOKEN compound_name IS_TOKEN SEPARATE_TOKEN ';'
	| subprog_spec IS_TOKEN SEPARATE_TOKEN ';'
	| PROTECTED_TOKEN BODY_TOKEN simple_name IS_TOKEN SEPARATE_TOKEN ';'
	;

exception_decl : def_id_s ':' EXCEPTION_TOKEN ';'
   {
      $$ := new Exception_Declaration_Token;
      Exception_Declaration_Token($$.all).Def_ID_S := Def_ID_S_Token_Ptr($1);

      if not In_Private then
         Insert(Tree , $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	;

except_handler_part : EXCEPTION_TOKEN exception_handler
	| except_handler_part exception_handler
	;

exception_handler : WHEN_TOKEN except_choice_s ARROW statement_s
	| WHEN_TOKEN identifier ':' except_choice_s ARROW statement_s
	;

except_choice_s : except_choice
	| except_choice_s '|' except_choice
	;

except_choice : name
	| OTHERS_TOKEN
	;

raise_stmt : RAISE_TOKEN name_opt ';'
	;

requeue_stmt : REQUEUE_TOKEN name ';'
	| REQUEUE_TOKEN name WITH_TOKEN ABORT_TOKEN ';'
	;

generic_decl : generic_formal_part subprog_spec ';'
   {
      Subprog_Token($2.all).Is_Generic := True;
      Subprog_Token($2.all).Generic_Part := Generic_Para_Token_Ptr($1);

      if not In_Private then
         Insert(Tree, $2);
      else
         Insert(Private_Tree, $2);
      end if;
   }
	| generic_formal_part pkg_spec ';'
	{
	   Package_Spec_Token($2.all).Is_Generic := True;
	   Package_Spec_Token($2.all).Generic_Part := Generic_Para_Token_Ptr($1);
	}
	;

generic_formal_part : GENERIC_TOKEN
   {
      --No generic parameters
      $$ := null;
   }
	| generic_formal_part generic_formal
	{
	   $$ := $2;
	   Generic_Para_Token($$.all).Next_Para := Generic_Para_Token_Ptr($1);
	   Generic_Para_Token($$.all).Line_Number := Get_Current_Line;
	}
	;

generic_formal : param ';'
   {
      $$ := new Generic_Param_Token;
      Generic_Param_Token($$.all).Line_Number := Get_Current_Line;
      Generic_Param_Token($$.all).Def_ID_S := Parameters_Token($1.all).Def_ID_S;
      Generic_Param_Token($$.all).Mode := Parameters_Token($1.all).Mode;
      Generic_Param_Token($$.all).Type_Param := Parameters_Token($1.all).Type_Param;
      Generic_Param_Token($$.all).Init := Parameters_Token($1.all).Init;

   }
	| TYPE_TOKEN simple_name generic_discrim_part_opt IS_TOKEN
             generic_type_def ';'
   {
      $$ := new Generic_Type_Para_Token;
      Generic_Type_Para_Token($$.all).Name := Dummy_String_Token($2.all).Str;
      Generic_Type_Para_Token($$.all).Discriminant := Discriminant_Token_Ptr($3);
      Generic_Type_Para_Token($$.all).Type_Def := Dummy_String_Token($5.all).Str;
   }
	| WITH_TOKEN PROCEDURE_TOKEN simple_name
	    formal_part_opt subp_default ';'
	{
	   $$ := new Generic_Proc_Para_Token;
	   Generic_Proc_Para_Token($$.all).Name := Dummy_String_Token($3.all).Str;
	   Generic_Proc_Para_Token($$.all).Parameters := Parameters_Token_Ptr($4);
	   Generic_Proc_Para_Token($$.all).Subp_Default := Dummy_String_Token($5.all).Str;
   }
	| WITH_TOKEN FUNCTION_TOKEN designator
	    formal_part_opt RETURN_TOKEN name subp_default ';'
	{
	   $$ := new Generic_Fun_Para_Token;
	   Generic_Fun_Para_Token($$.all).Name := Dummy_String_Token($3.all).Str;
	   Generic_Fun_Para_Token($$.all).Parameters := Parameters_Token_Ptr($4);
	   Generic_Fun_Para_Token($$.all).Return_Type := Dummy_String_Token($6.all).Str;
	   Generic_Fun_Para_Token($$.all).Subp_Default := Dummy_String_Token($7.all).Str;
   }

	| WITH_TOKEN PACKAGE_TOKEN simple_name IS_TOKEN NEW_TOKEN
            name '(' BOX ')' ';'
   {
      $$ := new Generic_Package_Token;
      Generic_Package_Token($$.all).Instanciation :=
      "with package " & Dummy_String_Token($3.all).Str &
      " is new " & Dummy_String_Token($6.all).Str &
      " (<>)";
   }
	| WITH_TOKEN PACKAGE_TOKEN simple_name IS_TOKEN NEW_TOKEN name ';'
	{
	   $$ := new Generic_Package_Token;
      Generic_Package_Token($$.all).Instanciation :=
      "with package " & Dummy_String_Token($3.all).Str &
      " is new " & Dummy_String_Token($6.all).Str;

   }
	| use_clause -- nothing to do because not really a generic parameters
	;

generic_discrim_part_opt :
   {
      $$ := null;
   }
	| discrim_part
	{
	   $$ := $1;
	}
	| '(' BOX ')'
	{
	   $$ := new Discriminant_Token;
         Discriminant_Token($$.all).Def_ID_S := new Def_ID_S_Token'(
         Ada.Finalization.Controlled with 0, To_Unbounded_String("<>"), null);
         Discriminant_Token($$.all).Type_Def := Null_Unbounded_String;
         Discriminant_Token($$.all).Init := Null_Unbounded_String;
   }
	;

subp_default :
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Null_Unbounded_String;
   }
	| IS_TOKEN name
	{
      $$ := $2;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str;
   }
	| IS_TOKEN Box
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("(<>)");
   }
	;

generic_type_def : '(' BOX ')'
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("(<>)");
   }
	| RANGE_TOKEN BOX
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("range (<>)");
   }
	| MOD_TOKEN BOX
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("mod (<>)");
   }
	| DELTA_TOKEN BOX
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("delta (<>)");
   }
	| DELTA_TOKEN BOX DIGITS_TOKEN BOX
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("delta (<>) digits (<>)");
   }
	| DIGITS_TOKEN BOX
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := To_Unbounded_String("digits (<>)");
   }
	| array_type
	{
      $$ := $1;

   }
	| access_type
	{
      $$ := $1;
   }
	| private_type
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Simple_Type_Token($1.all).Declaration_Part;
   }
	| generic_derived_type
	{
	   $$ := $1;
	}
	;

generic_derived_type : NEW_TOKEN subtype_ind
   {
      $$ := $2;
      Dummy_String_Token($$.all).Str := "new " & Dummy_String_Token($$.all).Str;
   }
	| NEW_TOKEN subtype_ind WITH_TOKEN PRIVATE_TOKEN
	{
      $$ := $2;
      Dummy_String_Token($$.all).Str := "new " & Dummy_String_Token($$.all).Str &
      " with private";
   }
	| ABSTRACT_TOKEN NEW_TOKEN subtype_ind WITH_TOKEN PRIVATE_TOKEN
	{
      $$ := $3;
      Dummy_String_Token($$.all).Str := "abstract new " & Dummy_String_Token($$.all).Str
      & " with private";
   }
	;

generic_subp_inst : subprog_spec IS_TOKEN generic_inst
   {
      $$ := new Generic_Subp_Inst_Token;
      Generic_Subp_Inst_Token($$.all).Line_Number := Get_Current_Line;
      Generic_Subp_Inst_Token($$.all).Subprog_Spec := Subprog_Token_Ptr($1);
      Generic_Subp_Inst_Token($$.all).Instanciation := "is " &
      Dummy_String_Token($3.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	;

generic_pkg_inst : PACKAGE_TOKEN compound_name IS_TOKEN generic_inst
   {
      $$ := new Generic_Pkg_Inst_Token;
      Generic_Pkg_Inst_Token($$.all).Line_Number := Get_Current_Line;
      Generic_Pkg_Inst_Token($$.all).Instanciation := "package " &
      Dummy_String_Token($2.all).Str & " is " &
      Dummy_String_Token($4.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	;

generic_inst : NEW_TOKEN name
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "new " & Dummy_String_Token($2.all).Str;
   }
	;

rep_spec : attrib_def
   {
      $$ := new Rep_Clause_Token;
      Rep_Clause_Token($$.all).Line_Number := Get_Current_Line;
      Rep_Clause_Token($$.all).Def := Dummy_String_Token($1.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	| record_type_spec
	{
	   $$ := new Rep_Clause_Token;
      Rep_Clause_Token($$.all).Line_Number := Get_Current_Line;
      Rep_Clause_Token($$.all).Def := Dummy_String_Token($1.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;
   }
	| address_spec
	{
	   $$ := new Rep_Clause_Token;
      Rep_Clause_Token($$.all).Line_Number := Get_Current_Line;
      Rep_Clause_Token($$.all).Def := Dummy_String_Token($1.all).Str;

      if not In_Private then
         Insert(Tree, $$);
      else
         Insert(Private_Tree, $$);
      end if;

	}
	;

attrib_def : FOR_TOKEN mark USE_TOKEN expression ';'
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "for " & Dummy_String_Token($2.all).Str & " use "
                                        & Dummy_String_Token($4.all).Str;
   }
	;

record_type_spec : FOR_TOKEN mark USE_TOKEN RECORD_TOKEN
                     align_opt comp_loc_s END_TOKEN RECORD_TOKEN ';'
   {
      $$ := new Dummy_String_Token;

      if Dummy_String_Token($2.all).Str /= Null_Unbounded_String then
         Dummy_String_Token($$.all).Str := "for " & Dummy_String_Token($2.all).Str &
                                           " use record";
      end if;

      if Dummy_String_Token($5.all).Str /= Null_Unbounded_String then
         Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str & ' ' &
                                           Dummy_String_Token($5.all).Str;
      end if;

      Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str & ' ' &
                                        Dummy_String_Token($6.all).Str & " end record";

   }
	;

align_opt :
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Null_Unbounded_String;

   }
	| AT_TOKEN MOD_TOKEN expression ';'
	{
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "at mod " & Dummy_String_Token($3.all).Str;

   }
	;

comp_loc_s :
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := Null_Unbounded_String;

   }
	| comp_loc_s mark AT_TOKEN expression RANGE_TOKEN range ';'
	{
      $$ := $1;
      Dummy_String_Token($$.all).Str := Dummy_String_Token($$.all).Str & ' ' &
                                        Dummy_String_Token($2.all).Str & " at " &
                                        Dummy_String_Token($4.all).Str & " range " &
                                        Dummy_String_Token($6.all).Str;

   }
	;

address_spec : FOR_TOKEN mark USE_TOKEN AT_TOKEN expression ';'
   {
      $$ := new Dummy_String_Token;
      Dummy_String_Token($$.all).Str := "for " & Dummy_String_Token($2.all).Str &
                                        " use at " & Dummy_String_Token($5.all).Str;
   }
	;

code_stmt : qualified ';'
	;


%%

-- ***********************************************************
-- *                                                         *
-- * Ada95_Parser                                            * SPEC
-- *                                                         *
-- ***********************************************************
with AdaDoc_Tree.List; use AdaDoc_Tree.List;
package Ada95_Parser is

  procedure Run (File_Name : in STRING);
  --| PURPOSE:
  --| Cause the Parser to execute.  This is simply a call to YYParse.

  procedure Display_Results;
  --| PURPOSE:
  --| Display final results on all files parsed so far.

  --Modified for AdaDoc

   --Main root of the tree
   Tree : Tree_Type;

   --Private tree
   Private_Tree : Tree_Type;

   --To know if we are in private part
   In_Private : Boolean := False;


end Ada95_Parser;

-- ***********************************************************
-- *                                                         *
-- * Ada95_Parser                                            * BODY
-- *                                                         *
-- ***********************************************************
with Ada95_Lexer;               use Ada95_Lexer;
with Ada95_Parser_Goto;         use Ada95_Parser_Goto;
with Ada95_Parser_Shift_Reduce; use Ada95_Parser_Shift_Reduce;
with Ada95_Parser_Tokens;       use Ada95_Parser_Tokens;
with Ada.Text_IO;               use Ada.Text_IO;
with Text_IO;
with AdaDoc_Tree;               use AdaDoc_Tree;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Finalization;
package body Ada95_Parser is

------------------------------------------------------------------
-- Local types and objects
------------------------------------------------------------------

  Echo             : BOOLEAN := FALSE;
  Number_of_Errors : NATURAL := 0;

------------------------------------------------------------------
-- Local routines
------------------------------------------------------------------

  -- ***********************************************************
  -- *                                                         *
  -- * Ada95_Parser.YYError                                    *
  -- *                                                         *
  -- ***********************************************************
  procedure YYError(S: in STRING := "Syntax Error") is
  --| PURPOSE:
  --| Output error message and increment Number_of_Errors
  begin -- YYError
    Put_Line(S & " line : " & Integer'Image(Get_Current_Line));
    Number_of_Errors := Number_of_Errors + 1;
    raise Syntax_Error;
  end YYError;

------------------------------------------------------------------
-- Local routines to manipulate YYSTYPE objects
------------------------------------------------------------------

  -- ***********************************************************
  -- *                                                         *
  -- * Ada95_Parser.Set                                        *
  -- *                                                         *
  -- ***********************************************************
  procedure Set (Result       : out STRING_BUFFER;
		 Input_String : in STRING) is
    Temp_Result : STRING_BUFFER;
  begin -- Set
    if Input_String'LENGTH <= Maximum_String_Length then
      Temp_Result.Last := Input_String'LENGTH;
      Temp_Result.Text(1..Temp_Result.Last) := Input_String;
    else
      Temp_Result.Last := Maximum_String_Length;
      Temp_Result.Text(1..Temp_Result.Last) :=
        Input_String(Input_String'FIRST .. Input_String'FIRST - 1 +
                     Maximum_String_Length);
    end if;
    Result := Temp_Result;
  end Set;

------------------------------------------------------------------
-- Local routines to handle action rules in the grammar
------------------------------------------------------------------

------------------------------------------------------------------
-- Local routines for performing the parse
------------------------------------------------------------------

  -- ***********************************************************
  -- *                                                         *
  -- * Ada95_Parser.YYParse                                    *
  -- *                                                         *
  -- ***********************************************************
  --| PURPOSE:
  --| Perform the parse of a file.
  --| YYParse is inserted below

##%procedure_parse

------------------------------------------------------------------
-- Routines exported by the specification
------------------------------------------------------------------

  -- ***********************************************************
  -- *                                                         *
  -- * Ada95_Parser.Run                                        *
  -- *                                                         *
  -- ***********************************************************
  procedure Run (File_Name : in STRING) is
  --| PURPOSE:
  --| Cause the Parser to execute.  This is simply a call to YYParse
  --| with a update of statistics.
  begin -- Run
    Ada95_Lexer.Reset (File_Name);
    Number_of_Errors := 0;
    begin
      YYParse;
    end;
    Ada95_Lexer.Close_Files;
  end Run;

  -- ***********************************************************
  -- *                                                         *
  -- * Ada95_Parser.Display_Results                            *
  -- *                                                         *
  -- ***********************************************************
  procedure Display_Results is
  --| PURPOSE:
  --| Display final results on all files processed so far.
  --| YOU HAVE TO FILL THIS IN
  begin -- Display_Results
    null;
  end Display_Results;

end Ada95_Parser;


