-------------------------------------------------------------------------------
-- (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.
--
--=============================================================================

separate (Dictionary)
function Get_Scalar_Attribute_Value
  (Base      : Boolean;
   Name      : LexTokenManager.Lex_String;
   Type_Mark : RawDict.Type_Info_Ref)
  return      LexTokenManager.Lex_String
is
   Result : LexTokenManager.Lex_String;

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

   function Get_Base_Attribute_Value
     (Name      : LexTokenManager.Lex_String;
      Type_Mark : RawDict.Type_Info_Ref)
     return      LexTokenManager.Lex_String
   --# global in Dict;
   --#        in LexTokenManager.State;
   is
      Result    : LexTokenManager.Lex_String;
      Base_Type : RawDict.Type_Info_Ref;
   begin
      -- set default case; override for various successes
      Result    := LexTokenManager.Null_String;
      Base_Type := Get_Base_Type (Type_Mark => Type_Mark);
      if Base_Type /= RawDict.Null_Type_Info_Ref then
         if LexTokenManager.Lex_String_Case_Insensitive_Compare (Lex_Str1 => Name,
                                                                 Lex_Str2 => LexTokenManager.First_Token) =
           LexTokenManager.Str_Eq then
            if RawDict.Get_Type_Discriminant (Type_Mark => Type_Mark) = Integer_Type_Item
              or else RawDict.Get_Type_Discriminant (Type_Mark => Type_Mark) = Enumeration_Type_Item
              or else RawDict.Get_Type_Discriminant (Type_Mark => Type_Mark) = Modular_Type_Item
              or else RawDict.Get_Type_Discriminant (Type_Mark => Type_Mark) = Floating_Point_Type_Item then
               Result := RawDict.Get_Type_Lower (Type_Mark => Base_Type);
            end if;
         elsif LexTokenManager.Lex_String_Case_Insensitive_Compare (Lex_Str1 => Name,
                                                                    Lex_Str2 => LexTokenManager.Last_Token) =
           LexTokenManager.Str_Eq then
            if RawDict.Get_Type_Discriminant (Type_Mark => Type_Mark) = Integer_Type_Item
              or else RawDict.Get_Type_Discriminant (Type_Mark => Type_Mark) = Enumeration_Type_Item
              or else RawDict.Get_Type_Discriminant (Type_Mark => Type_Mark) = Modular_Type_Item
              or else RawDict.Get_Type_Discriminant (Type_Mark => Type_Mark) = Floating_Point_Type_Item then
               Result := RawDict.Get_Type_Upper (Type_Mark => Base_Type);
            end if;
         end if;
      end if;
      return Result;
   end Get_Base_Attribute_Value;

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

   function Get_Attribute_Value
     (Name      : LexTokenManager.Lex_String;
      Type_Mark : RawDict.Type_Info_Ref)
     return      LexTokenManager.Lex_String
   --# global in Dict;
   --#        in LexTokenManager.State;
   is
      Result : LexTokenManager.Lex_String;
   begin
      if LexTokenManager.Lex_String_Case_Insensitive_Compare (Lex_Str1 => Name,
                                                              Lex_Str2 => LexTokenManager.Delta_Token) =
        LexTokenManager.Str_Eq
        or else LexTokenManager.Lex_String_Case_Insensitive_Compare (Lex_Str1 => Name,
                                                                     Lex_Str2 => LexTokenManager.Digits_Token) =
        LexTokenManager.Str_Eq then
         Result := RawDict.Get_Type_Error_Bound (Type_Mark => Type_Mark);
      elsif LexTokenManager.Lex_String_Case_Insensitive_Compare (Lex_Str1 => Name,
                                                                 Lex_Str2 => LexTokenManager.First_Token) =
        LexTokenManager.Str_Eq then
         if Type_Is_Scalar (Type_Mark => Type_Mark) then
            Result := RawDict.Get_Type_Lower (Type_Mark => Type_Mark);
         else
            Result := RawDict.Get_Type_Lower (Type_Mark => Get_Array_Index (Type_Mark => Type_Mark,
                                                                            Dimension => 1));
         end if;
      elsif LexTokenManager.Lex_String_Case_Insensitive_Compare (Lex_Str1 => Name,
                                                                 Lex_Str2 => LexTokenManager.Last_Token) =
        LexTokenManager.Str_Eq then
         if Type_Is_Scalar (Type_Mark => Type_Mark) then
            Result := RawDict.Get_Type_Upper (Type_Mark => Type_Mark);
         else
            Result := RawDict.Get_Type_Upper (Type_Mark => Get_Array_Index (Type_Mark => Type_Mark,
                                                                            Dimension => 1));
         end if;
      elsif LexTokenManager.Lex_String_Case_Insensitive_Compare (Lex_Str1 => Name,
                                                                 Lex_Str2 => LexTokenManager.Modulus_Token) =
        LexTokenManager.Str_Eq then
         Result := RawDict.Get_Type_Modulus (Type_Mark => Type_Mark);
      else
         Result := LexTokenManager.Null_String;
      end if;
      return Result;
   end Get_Attribute_Value;

begin -- Get_Scalar_Attribute_Value
   if Type_Mark = Get_Unknown_Type_Mark then
      Result := LexTokenManager.Null_String;
   elsif Base then
      Result := Get_Base_Attribute_Value (Name      => Name,
                                          Type_Mark => Get_Root_Type (Type_Mark => Type_Mark));
   else
      Result := Get_Attribute_Value (Name      => Name,
                                     Type_Mark => Type_Mark);
   end if;
   return Result;
end Get_Scalar_Attribute_Value;
