-------------------------------------------------------------------------------
-- (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 (Sem)
procedure Get_Subprogram_Anno_Key_Nodes
  (Node            : in     STree.SyntaxNode;
   Global_Node     :    out STree.SyntaxNode;
   Dependency_Node :    out STree.SyntaxNode;
   Declare_Node    :    out STree.SyntaxNode;
   Constraint_Node :    out STree.SyntaxNode)
is
begin
   Constraint_Node := Child_Node (Current_Node => Node);
   -- ASSUME Constraint_Node = moded_global_definition OR dependency_relation OR declare_annotation OR
   --                          procedure_constraint OR function_constraint
   if Syntax_Node_Type (Node => Constraint_Node) = SP_Symbols.function_constraint
     or else Syntax_Node_Type (Node => Constraint_Node) = SP_Symbols.procedure_constraint then
      -- ASSUME Constraint_Node = function_constraint OR procedure_constraint
      Global_Node     := STree.NullNode;
      Dependency_Node := STree.NullNode;
      Declare_Node    := STree.NullNode; -- only a constraint found
   elsif Syntax_Node_Type (Node => Constraint_Node) = SP_Symbols.declare_annotation then
      -- ASSUME Constraint_Node = declare_annotation
      Global_Node     := STree.NullNode;
      Dependency_Node := STree.NullNode;
      Declare_Node    := Constraint_Node;
      Constraint_Node := Last_Sibling_Of (Start_Node => Constraint_Node);
   elsif Syntax_Node_Type (Node => Constraint_Node) = SP_Symbols.dependency_relation then
      -- ASSUME Constraint_Node = dependency_relation
      Global_Node     := STree.NullNode;
      Dependency_Node := Constraint_Node;
      Constraint_Node := Last_Sibling_Of (Start_Node => Constraint_Node);
      Declare_Node    := Next_Sibling (Current_Node => Dependency_Node);
      -- ASSUME Declare_Node = declare_annotation OR procedure_constraint
      if Syntax_Node_Type (Node => Declare_Node) = SP_Symbols.procedure_constraint then
         -- ASSUME Declare_Node = procedure_constraint
         Declare_Node := STree.NullNode;
      elsif Syntax_Node_Type (Node => Declare_Node) /= SP_Symbols.declare_annotation then
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Declare_Node = declare_annotation OR procedure_constraint in Get_Subprogram_Anno_Key_Nodes");
      end if;
   elsif Syntax_Node_Type (Node => Constraint_Node) = SP_Symbols.moded_global_definition then
      -- ASSUME Constraint_Node = moded_global_definition
      Global_Node     := Constraint_Node;
      Constraint_Node := Last_Sibling_Of (Start_Node => Constraint_Node);
      Dependency_Node := Next_Sibling (Current_Node => Global_Node);
      -- ASSUME Dependency_Node = dependency_relation OR declare_annotation OR
      --                          procedure_constraint OR function_constraint
      if Syntax_Node_Type (Node => Dependency_Node) = SP_Symbols.procedure_constraint
        or else Syntax_Node_Type (Node => Dependency_Node) = SP_Symbols.function_constraint then
         -- ASSUME Dependency_Node = procedure_constraint OR function_constraint
         Dependency_Node := STree.NullNode;
         Declare_Node    := STree.NullNode;
      elsif Syntax_Node_Type (Node => Dependency_Node) = SP_Symbols.declare_annotation then
         -- ASSUME Dependency_Node = declare_annotation
         Declare_Node    := Dependency_Node;
         Dependency_Node := STree.NullNode;
      elsif Syntax_Node_Type (Node => Dependency_Node) = SP_Symbols.dependency_relation then
         -- ASSUME Dependency_Node = dependency_relation
         Declare_Node := Next_Sibling (Current_Node => Dependency_Node);
         -- ASSUME Declare_Node = declare_annotation OR procedure_constraint
         if Syntax_Node_Type (Node => Declare_Node) = SP_Symbols.procedure_constraint then
            -- ASSUME Declare_Node = procedure_constraint
            Declare_Node := STree.NullNode;
         elsif Syntax_Node_Type (Node => Declare_Node) /= SP_Symbols.declare_annotation then
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Declare_Node = declare_annotation OR procedure_constraint in Get_Subprogram_Anno_Key_Nodes");
         end if;
      else
         Declare_Node := STree.NullNode;
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Dependency_Node = dependency_relation OR declare_annotation OR " &
              "procedure_constraint OR function_constraint in Get_Subprogram_Anno_Key_Nodes");
      end if;
   else
      Global_Node     := STree.NullNode;
      Dependency_Node := STree.NullNode;
      Declare_Node    := STree.NullNode;
      Constraint_Node := STree.NullNode;
      SystemErrors.Fatal_Error
        (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Constraint_Node = moded_global_definition OR dependency_relation OR " &
           "declare_annotation OR procedure_constraint OR function_constraint in Get_Subprogram_Anno_Key_Nodes");
   end if;
   -- ASSUME Global_Node = moded_global_definition OR NULL
   SystemErrors.RT_Assert
     (C       => Global_Node = STree.NullNode
        or else Syntax_Node_Type (Node => Global_Node) = SP_Symbols.moded_global_definition,
      Sys_Err => SystemErrors.Invalid_Syntax_Tree,
      Msg     => "Expect Global_Node = moded_global_definition OR NULL in Get_Subprogram_Anno_Key_Nodes");
   -- ASSUME Dependency_Node = dependency_relation OR NULL
   SystemErrors.RT_Assert
     (C       => Dependency_Node = STree.NullNode
        or else Syntax_Node_Type (Node => Dependency_Node) = SP_Symbols.dependency_relation,
      Sys_Err => SystemErrors.Invalid_Syntax_Tree,
      Msg     => "Expect Dependency_Node = dependency_relation OR NULL in Get_Subprogram_Anno_Key_Nodes");
   -- ASSUME Declare_Node = declare_annotation OR NULL
   SystemErrors.RT_Assert
     (C       => Declare_Node = STree.NullNode or else Syntax_Node_Type (Node => Declare_Node) = SP_Symbols.declare_annotation,
      Sys_Err => SystemErrors.Invalid_Syntax_Tree,
      Msg     => "Expect Declare_Node = declare_annotation OR NULL in Get_Subprogram_Anno_Key_Nodes");
   -- ASSUME Constraint_Node = function_constraint OR procedure_constraint
   SystemErrors.RT_Assert
     (C       => Syntax_Node_Type (Node => Constraint_Node) = SP_Symbols.function_constraint
        or else Syntax_Node_Type (Node => Constraint_Node) = SP_Symbols.procedure_constraint,
      Sys_Err => SystemErrors.Invalid_Syntax_Tree,
      Msg     => "Expect Constraint_Node = function_constraint OR procedure_constraint in Get_Subprogram_Anno_Key_Nodes");
end Get_Subprogram_Anno_Key_Nodes;
