DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ B T

⟦bc691968b⟧ TextFile

    Length: 26676 (0x6834)
    Types: TextFile
    Names: »B«

Derivation

└─⟦a7d1ea751⟧ Bits:30000550 8mm tape, Rational 1000, !users!projects 94_04_11
    └─ ⟦129cab021⟧ »DATA« 
        └─⟦this⟧ 

TextFile

with Nodes;
with Lexical;
with Bounded_Strings;
with Gen_Stack;
with Error;
with Text_Io;
package body Symbol is

    type Object (Length : Positive);
    type Pobject is access Object;

    type Symbols (A_Kind : Kind := None) is
        record
            Name : Lexical.Lexeme;
            case A_Kind is
                when Category =>
                    Actors : Pobject := null;
                when Station =>
                    Sta_Type : Lexical.Lexeme;      -- Un nom de categorie
                    Sta_Adress : Natural;
                    Sta_Category : Pobject :=
                       null;  -- Ptr sur table des acteurs
                when Actor =>
                    Act_Type : Types := T_Void;
                    Act_Number : Natural range 0 .. Actor_Table_Size - 1 := 0;
                when Variable =>
                    Var_Type : Types := T_Void;
                    Var_Value : Integer := 0;
                when Effect | Scene =>
                    Local_Table : Pobject := null;
                    Code : Nodes.Pnode := null;
                when Begining =>
                    Beg_Code : Nodes.Pnode := null;
                when Argument =>
                    Arg_Number : Positive := 1;
                    Arg_Value : Natural := 0;    -- Un index dans la globale
                when None =>
                    null;
            end case;
        end record;
    type Psymbols is access Symbols;       -- MUTABLE !!!
    type Symbols_Array is array (Positive range <>) of Psymbols;

    type Object (Length : Positive) is
        record
            The_Previous : Pobject;
            The_Index : Natural;
            The_Content : Symbols_Array (1 .. Length);
        end record;

-- Pile des tables  =>  profondeur d'appel de 20
    package Table_Stack is new Gen_Stack (20, Pobject);

-- Variables du package symbol

    Null_Lexeme : Lexical.Lexeme;
    Number : Natural := 0;
    Current_Table : Pobject := null;                -- Table Courante (Active)
    Global_Table : Pobject := null;                 -- Table Globale
    Symbol_Table_Stack : Table_Stack.Object;        -- Pile des tables

-- Fonctions de gestion locales

    function Is_In_Table (The_Name : in Lexical.Lexeme; The_Table : in Pobject)
                         return Boolean is
    begin
        for I in 1 .. The_Table.The_Index loop
            if Bounded_Strings.Is_Equal
                  (The_Table.The_Content (I).Name, The_Name) then
                return True;
            end if;
        end loop;
        return False;
    end Is_In_Table;

    function Is_Existing (The_Name : in Lexical.Lexeme) return Boolean is
        Table_Pointer : Pobject;
    begin
        Table_Pointer := Current_Table;
        while Table_Pointer /= null loop
            if Is_In_Table (The_Name, Table_Pointer) then
                return True;
            end if;
            Table_Pointer := Table_Pointer.The_Previous;
        end loop;
        return False;
    end Is_Existing;

    function Get_Index (From_Name : in Lexical.Lexeme; In_Table : in Pobject)
                       return Positive is
    begin
        for I in 1 .. In_Table.The_Index loop
            if Bounded_Strings.Is_Equal
                  (In_Table.The_Content (I).Name, From_Name) then
                return I;
            end if;
        end loop;
    end Get_Index;

    function Is_Arg_Number (The_Number : in Positive) return Boolean is
    begin
        for I in 1 .. Current_Table.The_Index loop
            if (Current_Table.The_Content (I).A_Kind = Argument) then
                if (Current_Table.The_Content (I).Arg_Number = The_Number) then
                    return True;
                end if;
            end if;
        end loop;
        return False;
    end Is_Arg_Number;


-- Creation/Liberation

    procedure New_Table (Length : in Positive) is
        Table_Pointer : Pobject;
    begin
        Number := 0;
        if (Current_Table = null) then
            Current_Table := new Object (Length);
            Current_Table.The_Previous := null;
            Current_Table.The_Index := 0;
            Global_Table :=
               Current_Table;     -- Init du pointeur sur la globale
        else
            Table_Pointer := new Object (Length);
            Table_Pointer.The_Previous := Current_Table;
            Table_Pointer.The_Index := 0;
            case Current_Table.The_Content (Current_Table.The_Index).A_Kind is
                when Category =>
                    -- On rattache la table des acteurs a la categorie correspondante
                    -- Suppose que la derniere entree dans la table a ete cette categorie
                    Current_Table.The_Content (Current_Table.The_Index).
                       Actors := Table_Pointer;
                when Effect | Scene =>
                    -- On rattache la table locale a l'effet ou la scene correspondante
                    -- Suppose que la derniere entree dans la table a ete cet effet ou
                    -- cette scene !
                    Current_Table.The_Content (Current_Table.The_Index).
                       Local_Table := Table_Pointer;
                when Station | Actor | Variable | Begining | Argument | None =>
                    null;
            end case;
            Current_Table := Table_Pointer;
        end if;
    end New_Table;

    procedure Release_Table is
    begin
        if Current_Table /= Global_Table then
            Current_Table := Global_Table;
        end if;
    end Release_Table;


    procedure Init_Tables_Stack is
    begin
        Table_Stack.Push (Symbol_Table_Stack, Global_Table);
    end Init_Tables_Stack;

    procedure Set_Current_Table (Name : in Lexical.Lexeme) is
        use Table_Stack;
        Crt_Index : Positive;
    begin
        if not Is_In_Table (Name, Global_Table) then
            Error.Handle (Bounded_Strings.Image (Name) &
                          " absent de la table !", Error.Internal);
        else
            if Is_Full (Symbol_Table_Stack) then
                Error.Handle ("pile des tables pleine !", Error.Internal);
            else
                Crt_Index := Get_Index (Name, Global_Table);
                Current_Table :=
                   Global_Table.The_Content (Crt_Index).Local_Table;
                Push (Symbol_Table_Stack, Current_Table);
            end if;
        end if;
    end Set_Current_Table;

    procedure Reset_Current_Table is
        use Table_Stack;
    begin
        if Is_Empty (Symbol_Table_Stack) then
            Error.Handle ("pile des tables vide !", Error.Internal);
            Current_Table := Global_Table;
            Init_Tables_Stack;
        else
            Pop (Symbol_Table_Stack);
            Current_Table := Get_Top (Symbol_Table_Stack);
        end if;
    end Reset_Current_Table;


    -- Modification

    procedure Add (The_Name : in Lexical.Lexeme; Of_Kind : in Kind) is
        Table_Pointer : Pobject;
        Crt_Index : Positive;
    begin
        if Current_Table.The_Index < Current_Table.Length then
            if Is_Existing (The_Name) then
                if Is_In_Table (The_Name, Global_Table) then
                    Table_Pointer := Global_Table;
                else
                    Table_Pointer := Current_Table;
                end if;
                Crt_Index := Get_Index (The_Name, Table_Pointer);
                if Table_Pointer.The_Content (Crt_Index).A_Kind /= Variable then
                    Error.Handle ("nom d'identificateur " &
                                  Bounded_Strings.Image (The_Name) &
                                  " deja utilise !", Error.External);
                end if;
            else
                Current_Table.The_Index := Current_Table.The_Index + 1;
                case Of_Kind is
                    when Category =>
                        Current_Table.The_Content (Current_Table.The_Index) :=
                           new Symbols'(A_Kind => Category,
                                        Name => The_Name,
                                        Actors => null);
                    when Station =>
                        Current_Table.The_Content (Current_Table.The_Index) :=
                           new Symbols'(A_Kind => Station,
                                        Name => The_Name,
                                        Sta_Type => Null_Lexeme,
                                        Sta_Adress => 0,
                                        Sta_Category => null);
                    when Actor =>
                        Current_Table.The_Content (Current_Table.The_Index) :=
                           new Symbols'(A_Kind => Actor,
                                        Name => The_Name,
                                        Act_Type => T_Error,
                                        Act_Number => Number);
                        Number := Number + 1;
                    when Variable =>
                        Current_Table.The_Content (Current_Table.The_Index) :=
                           new Symbols'(A_Kind => Variable,
                                        Name => The_Name,
                                        Var_Type => T_Error,
                                        Var_Value => 0);
                    when Effect =>
                        Current_Table.The_Content (Current_Table.The_Index) :=
                           new Symbols'(A_Kind => Effect,
                                        Name => The_Name,
                                        Local_Table => null,
                                        Code => null);
                    when Scene =>
                        Current_Table.The_Content (Current_Table.The_Index) :=
                           new Symbols'(A_Kind => Scene,
                                        Name => The_Name,
                                        Local_Table => null,
                                        Code => null);
                    when Begining =>
                        Current_Table.The_Content (Current_Table.The_Index) :=
                           new Symbols'(A_Kind => Begining,
                                        Name => The_Name,
                                        Beg_Code => null);
                    when Argument =>
                        Number := Number +
                                     1;           -- car Number init et raj a 0
                        Current_Table.The_Content (Current_Table.The_Index) :=
                           new Symbols'(A_Kind => Argument,
                                        Name => The_Name,
                                        Arg_Number => Number,
                                        Arg_Value => 0);
                    when None =>
                        null;
                end case;
            end if;
        else
            Error.Handle ("table des symboles pleine !!", Error.Internal);
        end if;
    end Add;

    procedure Set_Code (Name : in Lexical.Lexeme; The_Code : in Nodes.Pnode) is
        Crt_Index : Positive;
    begin
        if not Is_In_Table (Name, Global_Table) then
            Error.Handle ("symbole absent de la table globale !",
                          Error.Internal);
        else
            Crt_Index := Get_Index (Name, Global_Table);
            case Global_Table.The_Content (Crt_Index).A_Kind is
                when Effect | Scene =>
                    Global_Table.The_Content (Crt_Index).Code := The_Code;
                when Begining =>
                    Global_Table.The_Content (Crt_Index).Beg_Code := The_Code;
                when Category | Actor | Station | Variable | Argument | None =>
                    null;
            end case;
        end if;
    end Set_Code;

    procedure Set_Value (Name : in Lexical.Lexeme; The_Value : in Integer) is
        Table_Pointer : Pobject;
        Crt_Index : Positive;
    begin
        if not Is_Existing (Name) then
            Error.Handle (Bounded_Strings.Image (Name) & " inexistant !",
                          Error.Internal);
        else
            if Is_In_Table (Name, Current_Table) then
                Table_Pointer := Current_Table;
            else
                Table_Pointer := Global_Table;
            end if;
            Crt_Index := Get_Index (Name, Table_Pointer);
            case Table_Pointer.The_Content (Crt_Index).A_Kind is
                when Station =>
                    Table_Pointer.The_Content (Crt_Index).Sta_Adress :=
                       The_Value;
                when Variable =>
                    Table_Pointer.The_Content (Crt_Index).Var_Value :=
                       The_Value;
                when Category | Actor | Effect | Scene |
                     Argument | Begining | None =>
                    null;
            end case;
        end if;
    end Set_Value;

    procedure Set_Arg_Value (With_Value : in Lexical.Lexeme;
                             Arg_Number : in Positive) is
        Crt_Index : Positive;
    begin
        if not Is_Arg_Number (Arg_Number) then
            Error.Handle ("argument " & Integer'Image (Arg_Number) &
                          " inexistant !", Error.Internal);
        else
            if not Is_In_Table (With_Value, Global_Table) then
                Error.Handle ("station " & Bounded_Strings.Image (With_Value) &
                              " inexistante !", Error.Internal);
            else
                Crt_Index := Get_Index (With_Value, Global_Table);
                Current_Table.The_Content (Arg_Number).Arg_Value := Crt_Index;
            end if;
        end if;
    end Set_Arg_Value;

    procedure Set_Type (Name : in Lexical.Lexeme; The_Type : in Types) is
        Crt_Index : Positive;
    begin
        if not Is_In_Table (Name, Current_Table) then
            Error.Handle (Bounded_Strings.Image (Name) & " inexistant !",
                          Error.External);
        else
            Crt_Index := Get_Index (Name, Current_Table);
            case Current_Table.The_Content (Crt_Index).A_Kind is
                when Variable =>
                    Current_Table.The_Content (Crt_Index).Var_Type := The_Type;
                when Actor =>
                    Current_Table.The_Content (Crt_Index).Act_Type := The_Type;
                when Category | Station | Argument |
                     Effect | Scene | Begining | None =>
                    null;
            end case;
        end if;
    end Set_Type;

    procedure Set_Type (From_Station : in Lexical.Lexeme;
                        With_Category : in Lexical.Lexeme) is
        Crt_Index : Positive;
    begin
        if not Is_In_Table (From_Station, Global_Table) then
            Error.Handle ("station " & Bounded_Strings.Image (From_Station) &
                          " inexistante !", Error.Internal);
        else
            if not Is_In_Table (With_Category, Global_Table) then
                Error.Handle ("categorie " &
                              Bounded_Strings.Image (With_Category) &
                              " inexistante !", Error.External);
            else
                Crt_Index := Get_Index (From_Station, Global_Table);
                if (Global_Table.The_Content (Crt_Index).A_Kind = Station) then
                    Bounded_Strings.Affect
                       (Global_Table.The_Content (Crt_Index).Sta_Type,
                        With_Category);
                    Global_Table.The_Content (Crt_Index).Sta_Category :=
                       Global_Table.The_Content
                          (Get_Index (With_Category, Current_Table)).Actors;
                else
                    null;
                end if;
            end if;
        end if;
    end Set_Type;

-- Consultation

    function Get_Code (From_Name : in Lexical.Lexeme) return Nodes.Pnode is
        Crt_Index : Positive;
    begin
        if not Is_In_Table (From_Name, Global_Table) then
            Error.Handle
               ("code de " & Bounded_Strings.Image (From_Name) & " absent !",
                Error.Internal);
            return null;
        else
            Crt_Index := Get_Index (From_Name, Global_Table);
            case Global_Table.The_Content (Crt_Index).A_Kind is
                when Effect | Scene =>
                    return Global_Table.The_Content (Crt_Index).Code;
                when Begining =>
                    return Global_Table.The_Content (Crt_Index).Beg_Code;
                when Category | Actor | Station | Variable | Argument | None =>
                    return null;
            end case;
        end if;
    end Get_Code;

    function Get_Value (From_Name : in Lexical.Lexeme) return Integer is
        Crt_Index : Positive;
        Table_Pointer : Pobject;
    begin
        if not Is_Existing (From_Name) then
            Error.Handle (Bounded_Strings.Image (From_Name) & " inexistant !",
                          Error.Internal);
            return 0;
        else
            if Is_In_Table (From_Name, Current_Table) then
                Table_Pointer := Current_Table;
            else
                Table_Pointer := Global_Table;
            end if;
            Crt_Index := Get_Index (From_Name, Table_Pointer);
            case Table_Pointer.The_Content (Crt_Index).A_Kind is
                when Station =>
                    return Table_Pointer.The_Content (Crt_Index).Sta_Adress;
                when Variable =>
                    return Table_Pointer.The_Content (Crt_Index).Var_Value;
                when Argument =>
                    Crt_Index :=
                       Table_Pointer.The_Content (Crt_Index).Arg_Value;
                    return Global_Table.The_Content (Crt_Index).Sta_Adress;
                when Category | Actor | Effect | Scene | Begining | None =>
                    return 0;
            end case;
        end if;
    end Get_Value;

    function Get_Effectfiv_Arg_Name
                (Formal_Param : in Lexical.Lexeme) return Lexical.Lexeme is
        use Table_Stack;
        My_Table : Pobject;
        Crt_Index : Positive;
    begin  
        if Is_In_Table (Formal_Param, Global_Table) then
            return Formal_Param;
        else
            Pop (Symbol_Table_Stack);
            My_Table := Get_Top (Symbol_Table_Stack);
        end if;

        if not Is_In_Table (Formal_Param, My_Table) then
            Error.Handle ("argument " & Bounded_Strings.Image (Formal_Param) &
                          " inexistant !", Error.Internal);
            Push (Symbol_Table_Stack, Current_Table);
            return Null_Lexeme;  
        else
            Crt_Index := Get_Index (Formal_Param, My_Table);
            Crt_Index := My_Table.The_Content (Crt_Index).Arg_Value;  
            Push (Symbol_Table_Stack, Current_Table);
            return Global_Table.The_Content (Crt_Index).Name;
        end if;
    end Get_Effectfiv_Arg_Name;


    function Get_Sta_Actor
                (In_Station : in Lexical.Lexeme; From_Actor : in Lexical.Lexeme)
                return Integer is
        Crt_Index : Positive;
        Table_Pointer : Pobject;
    begin
        if not Is_In_Table (In_Station, Global_Table) then
            Error.Handle ("station " & Bounded_Strings.Image (In_Station) &
                          " inexistante !", Error.Internal);
            return 0;
        else
            Crt_Index := Get_Index (In_Station, Global_Table);
            Table_Pointer := Global_Table.The_Content (Crt_Index).Sta_Category;
            if not Is_In_Table (From_Actor, Table_Pointer) then
                Error.Handle ("acteur " & Bounded_Strings.Image (From_Actor) &
                              " inexistant !", Error.Internal);
                return 0;
            else
                Crt_Index := Get_Index (From_Actor, Table_Pointer);
                return Table_Pointer.The_Content (Crt_Index).Act_Number;
            end if;
        end if;
    end Get_Sta_Actor;

    function Get_Arg_Actor
                (In_Station : in Lexical.Lexeme; From_Actor : in Lexical.Lexeme)
                return Integer is
        Crt_Index : Positive;
        Table_Pointer : Pobject;
    begin
        Crt_Index := Get_Index (In_Station, Current_Table);
        Crt_Index := Current_Table.The_Content (Crt_Index).Arg_Value;
        Table_Pointer := Global_Table.The_Content (Crt_Index).Sta_Category;
        if not Is_In_Table (From_Actor, Table_Pointer) then
            Error.Handle ("acteur " & Bounded_Strings.Image (From_Actor) &
                          " inexistant !", Error.Internal);
            return 0;
        else
            Crt_Index := Get_Index (From_Actor, Table_Pointer);
            return Table_Pointer.The_Content (Crt_Index).Act_Number;
        end if;
    end Get_Arg_Actor;

    function Get_Actor_Number
                (In_Station : in Lexical.Lexeme; From_Actor : in Lexical.Lexeme)
                return Integer is
        Crt_Index : Positive;
        Table_Pointer : Pobject;
    begin
        if not Is_In_Table (In_Station, Current_Table) then
            Table_Pointer := Global_Table;
        else
            Table_Pointer := Current_Table;
        end if;

        Crt_Index := Get_Index (In_Station, Table_Pointer);
        if (Table_Pointer.The_Content (Crt_Index).A_Kind = Argument) then
            return Get_Arg_Actor (In_Station, From_Actor);
        else
            return Get_Sta_Actor (In_Station, From_Actor);
        end if;
    end Get_Actor_Number;

    function Get_Type (From_Name : in Lexical.Lexeme) return Types is
        Crt_Index : Positive;
        Table_Pointer : Pobject;
    begin
        if not Is_Existing (From_Name) then
            Error.Handle (Bounded_Strings.Image (From_Name) & " inexistant !",
                          Error.Internal);
            return T_Error;
        else
            if Is_In_Table (From_Name, Current_Table) then
                Table_Pointer := Current_Table;
            else
                Table_Pointer := Global_Table;
            end if;
            Crt_Index := Get_Index (From_Name, Table_Pointer);
            case Table_Pointer.The_Content (Crt_Index).A_Kind is
                when Category =>
                    return T_Category;
                when Station =>
                    return T_Station;
                when Variable =>
                    return Current_Table.The_Content (Crt_Index).Var_Type;
                when Effect =>
                    return T_Effect;
                when Scene =>
                    return T_Scene;
                when Begining =>
                    return T_Begining;
                when Argument =>
                    return Get_Type (Global_Table.The_Content
                                        (Table_Pointer.The_Content (Crt_Index).
                                         Arg_Value).Name);
                when Actor | None =>
                    return T_Error;
            end case;
        end if;
    end Get_Type;

    function Get_Type
                (In_Station : in Lexical.Lexeme; From_Actor : in Lexical.Lexeme)
                return Types is
        Crt_Index : Positive;
        Table_Pointer : Pobject;
    begin
        if not Is_In_Table (In_Station, Global_Table) then
            Error.Handle ("station " & Bounded_Strings.Image (From_Actor) &
                          " inexistante !", Error.External);
            return T_Error;
        else
            Crt_Index := Get_Index (In_Station, Global_Table);
            Table_Pointer := Global_Table.The_Content (Crt_Index).Actors;
            if not Is_In_Table (From_Actor, Table_Pointer) then
                Error.Handle ("acteur " & Bounded_Strings.Image (From_Actor) &
                              "inexistant pour cette station !",
                              Error.External);
                return T_Error;
            else
                Crt_Index := Get_Index (From_Actor, Table_Pointer);
                return Table_Pointer.The_Content (Crt_Index).Act_Type;
            end if;
        end if;
    end Get_Type;


-- Tests

    procedure Print_Recur (P : in Pobject) is
        use Text_Io;
        Done : Boolean := False;
        I : Natural;
        Index : Natural;
    begin
        I := 1;
        Put_Line ("Debut-------------");
        while ((P /= null) and then (not Done)) loop
            Put (Integer'Image (I) & " ");
            Put (Bounded_Strings.Image (P.The_Content (I).Name) & " ");
            case P.The_Content (I).A_Kind is
                when Category =>
                    Put_Line ("CAT");
                    Print_Recur (P.The_Content (I).Actors);
                when Station =>
                    Put (Bounded_Strings.Image (P.The_Content (I).Sta_Type));
                    Put_Line (Integer'Image (P.The_Content (I).Sta_Adress));
                    -- Print_Recur (P.The_Content(I).Sta_Category);
                when Actor =>
                    Put ("ACT ");
                    Put_Line (Integer'Image (P.The_Content (I).Act_Number));
                when Variable =>
                    Put ("VAR = ");
                    Put_Line (Integer'Image (Get_Value
                                                (P.The_Content (I).Name)));
                when Effect =>
                    Put_Line ("EFF");
                    Current_Table := P.The_Content (I).Local_Table;
                    Print_Recur (Current_Table);
                    Release_Table;
                when Scene =>
                    Put_Line ("SCE");
                    Current_Table := P.The_Content (I).Local_Table;
                    Print_Recur (Current_Table);
                    Release_Table;
                when Argument =>
                    Put ("ARG");
                    Put (Integer'Image (P.The_Content (I).Arg_Number) & " : ");
                    Index := P.The_Content (I).Arg_Value;
                    if Index /= 0 then
                        Put (Bounded_Strings.Image
                                (Global_Table.The_Content (Index).Name));
                        Put_Line (Integer'Image (Get_Value
                                                    (P.The_Content (I).Name)));
                    else
                        Put_Line ("0");
                    end if;
                when Begining =>
                    Put_Line ("BEG");
                when None =>
                    null;
            end case;

            if I >= P.The_Index then
                Done := True;
            else
                I := I + 1;
            end if;
        end loop;
        Put_Line ("Fin--------------");
    end Print_Recur;

    procedure Print is
    begin
        Print_Recur (Current_Table);
    end Print;

end Symbol;