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

with SLI;

separate (Sem.Walk_Expression_P)
procedure Wf_Identifier
  (Node     : in     STree.SyntaxNode;
   Scope    : in     Dictionary.Scopes;
   E_Stack  : in out Exp_Stack.Exp_Stack_Type;
   The_Heap : in out Heap.HeapRecord;
   Ref_Var  : in     SeqAlgebra.Seq;
   Context  : in     Sem.Tilde_Context)
is
   Sym       : Dictionary.Symbol;
   Next_Node : STree.SyntaxNode;
begin
   if Context = Sem.Code then
      Sym :=
        Dictionary.LookupItem
        (Name              => STree.Node_Lex_String (Node => Node),
         Scope             => Scope,
         Context           => Dictionary.ProgramContext,
         Full_Package_Name => False);
   else
      Sym :=
        Dictionary.LookupItem
        (Name              => STree.Node_Lex_String (Node => Node),
         Scope             => Scope,
         Context           => Dictionary.ProofContext,
         Full_Package_Name => False);
      if not Dictionary.Is_Null_Symbol (Sym) and then ErrorHandler.Generate_SLI then
         SLI.Generate_Xref_Symbol
           (Comp_Unit      => ContextManager.Ops.Current_Unit,
            Parse_Tree     => Node,
            Symbol         => Sym,
            Is_Declaration => False);
      end if;
   end if;

   if not Dictionary.Is_Null_Symbol (Sym) then
      STree.Set_Node_Lex_String (Sym  => Sym,
                                 Node => Node);
   end if;

   if Dictionary.IsPackage (Sym) then
      Exp_Stack.Push
        (X     => Sem.Exp_Record'(Type_Symbol             => Dictionary.GetUnknownTypeMark,
                                  Other_Symbol            => Sym,
                                  Stream_Symbol           => Dictionary.NullSymbol,
                                  Tagged_Parameter_Symbol => Dictionary.NullSymbol,
                                  Variable_Symbol         => Dictionary.NullSymbol,
                                  Param_Count             => 0,
                                  Param_List              => Lists.Null_List,
                                  Sort                    => Sem.Is_Package,
                                  Arg_List_Found          => False,
                                  Is_AVariable            => False,
                                  Is_An_Entire_Variable   => False,
                                  Errors_In_Expression    => False,
                                  Has_Operators           => False,
                                  Is_Static               => False,
                                  Is_Constant             => False,
                                  Is_ARange               => False,
                                  String_Value            => LexTokenManager.Null_String,
                                  Value                   => Maths.NoValue,
                                  Range_RHS               => Maths.NoValue),
         Stack => E_Stack);
   else
      Stack_Identifier
        (Sym           => Sym,
         Id_Str        => STree.Node_Lex_String (Node => Node),
         Node          => Node,
         Prefix        => Dictionary.NullSymbol,
         Scope         => Scope,
         E_Stack       => E_Stack,
         The_Heap      => The_Heap,
         Ref_Var       => Ref_Var,
         Dotted        => False,
         Context       => Context,
         Is_Annotation => Context /= Sem.Code);
   end if;

   if Context /= Sem.Code then
      Next_Node := STree.Next_Sibling (Current_Node => Node);
      -- ASSUME Next_Node = tilde OR percent OR NULL
      if Next_Node /= STree.NullNode then
         -- ASSUME Next_Node = tilde OR percent
         -- identifier may have ~ or % after it
         case STree.Syntax_Node_Type (Node => Next_Node) is
            when SP_Symbols.tilde =>
               -- ASSUME Next_Node = tilde
               Wf_Tilde
                 (Node_Pos => STree.Node_Position (Node => Next_Node),
                  Scope    => Scope,
                  E_Stack  => E_Stack,
                  Context  => Context);
            when SP_Symbols.percent =>
               -- ASSUME Next_Node = percent
               Wf_Percent (Node_Pos => STree.Node_Position (Node => Next_Node),
                           Scope    => Scope,
                           E_Stack  => E_Stack);
            when others =>
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                  Msg     => "Expect Next_Node = tilde OR percent OR NULL in Wf_Identifier");
         end case;
      end if;
   end if;
end Wf_Identifier;
