-- $Header: /dc/uc/self/arcadia/ayacc/src/RCS/tokens_file_body.a,v 1.2 1993/05/31 22:36:35 self Exp self $

-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
--    The primary authors of ayacc were David Taback and Deepak Tolani.
--    Enhancements were made by Ronald J. Schmalz.
--
--    Send requests for ayacc information to ayacc-info@ics.uci.edu
--    Send bug reports for ayacc to ayacc-bugs@ics.uci.edu
--
-- Redistribution and use in source and binary forms are permitted
-- provided that the above copyright notice and this paragraph are
-- duplicated in all such forms and that any documentation,
-- advertising materials, and other materials related to such
-- distribution and use acknowledge that the software was developed
-- by the University of California, Irvine.  The name of the
-- University may not be used to endorse or promote products derived
-- from this software without specific prior written permission.
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
-- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-- WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

-- Module       : tokens_file_body.ada
-- Component of : ayacc
-- Version      : 1.2
-- Date         : 11/21/86  12:38:23
-- SCCS File    : disk21~/rschm/hasee/sccs/ayacc/sccs/sxtokens_file_body.ada

-- $Header: /dc/uc/self/arcadia/ayacc/src/RCS/tokens_file_body.a,v 1.2 1993/05/31 22:36:35 self Exp self $
-- $Log: tokens_file_body.a,v $
-- Revision 1.2  1993/05/31  22:36:35  self
-- added exception handler when opening files
--
-- Revision 1.1  1993/05/31  22:14:38  self
-- Initial revision
--
--Revision 1.1  88/08/08  14:43:01  arcadia
--Initial revision
--
-- Revision 0.1  86/04/01  15:14:29  ada
--  This version fixes some minor bugs with empty grammars
--  and $$ expansion. It also uses vads5.1b enhancements
--  such as pragma inline.
--
--
-- Revision 0.0  86/02/19  18:54:19  ada
--
-- These files comprise the initial version of Ayacc
-- designed and implemented by David Taback and Deepak Tolani.
-- Ayacc has been compiled and tested under the Verdix Ada compiler
-- version 4.06 on a vax 11/750 running Unix 4.2BSD.
--

with Ayacc_File_Names, Source_File, Symbol_Table, Text_Io;

with String_Pkg;
with Options;
package body Tokens_File is

   -- SCCS_ID : constant String := "@(#) tokens_file_body.ada, Version 1.2";
   -- Rcs_ID : constant String := "$Header: /dc/uc/self/arcadia/ayacc/src/RCS/tokens_file_body.a,v 1.2 1993/05/31 22:36:35 self Exp self $";

   Package_Header_Generated : Boolean := False;

   T_File : Text_Io.File_Type;

   procedure Open is
      use Text_Io;
   begin
      Create (T_File, Out_File, Ayacc_File_Names.Get_Tokens_File_Name);
   exception
      when Name_Error | Use_Error =>
         Put_Line
           ("Ayacc: Error Opening """ & Ayacc_File_Names.Get_Tokens_File_Name &
            """.");
         raise;
   end Open;

   function Tokens_Package_Header_Has_Been_Generated return Boolean is
   begin
      return Package_Header_Generated;
   end Tokens_Package_Header_Has_Been_Generated;

   procedure Start_Tokens_Package is
   begin
      if not Package_Header_Generated then
         if Options.Package_Private then
            Write ("private ");
         end if;
         Writeln ("package " & Ayacc_File_Names.Tokens_Unit_Name & " is");
         Writeln ("");
         Package_Header_Generated := True;
      end if;
   end Start_Tokens_Package;

   procedure Close is
      use Text_Io;
   begin
      Close (T_File);
   end Close;

   procedure Write (S : in String) is
      use Text_Io;
   begin
      Put (T_File, S);
   end Write;

   procedure Writeln (S : in String) is
      use Text_Io;
   begin
      Put_Line (T_File, S);
   end Writeln;

   procedure Complete_Tokens_Package is

      Keep_Token_Case : constant Boolean := Options.Keep_Token_Case;
      Tokens_On_Line  : Natural          := 1;
      use String_Pkg;
      use Symbol_Table;

   begin

      if not Package_Header_Generated then
         Start_Tokens_Package;
      end if;

      if not Options.Reentrant then
         Writeln ("   YYLVal, YYVal : YYSType;");
      end if;
      Writeln ("   type Token is");
      Write ("        (");

      for I in First_Symbol (Terminal) .. Last_Symbol (Terminal) - 1 loop
         if Tokens_On_Line = 4 then
            if Keep_Token_Case then
               Write (Get_Symbol_Name (I));
            else
               Write (Value (Mixed (Get_Symbol_Name (I))));
            end if;
            Writeln (",");
            Write ("         ");
            Tokens_On_Line := 1;
         else
            if Keep_Token_Case then
               Write (Get_Symbol_Name (I));
            else
               Write (Value (Mixed (Get_Symbol_Name (I))));
            end if;
            Write (", ");
         end if;
         Tokens_On_Line := Tokens_On_Line + 1;
      end loop;

      if Keep_Token_Case then
         Write (Get_Symbol_Name (Last_Symbol (Terminal)));
      else
         Write (Value (Mixed (Get_Symbol_Name (Last_Symbol (Terminal)))));
      end if;
      Writeln (");");
      Writeln ("");
      Writeln ("   Syntax_Error : exception;");
      Writeln ("");
      Writeln ("end " & Ayacc_File_Names.Tokens_Unit_Name & ";");

   end Complete_Tokens_Package;

   procedure Make_C_Lex_Package is
      use Symbol_Table, Text_Io;

      The_Define_File : File_Type;
      The_Ada_File    : File_Type;

      type Symbol_Rec is record
         Name   : String (1 .. Source_File.Maximum_Line_Length);
         Length : Natural;
      end record;

      Sym_Name : Symbol_Rec;

      function Convert (S : String) return Symbol_Rec is
         Result : Symbol_Rec;
      begin
         Result.Name (1 .. S'Length) := S;
         Result.Length               := S'Length;
         return Result;
      end Convert;

   begin

      Create (The_Ada_File, Out_File, Ayacc_File_Names.Get_C_Lex_File_Name);

      Put_Line
        (The_Ada_File,
         "with " & Ayacc_File_Names.Tokens_Unit_Name & ";  use " &
         Ayacc_File_Names.Tokens_Unit_Name & ";");
      Put_Line
        (The_Ada_File, "package " & Ayacc_File_Names.C_Lex_Unit_Name & " is");
      Put_Line (The_Ada_File, "    function YYLex return Token;");
      Put_Line (The_Ada_File, "end " & Ayacc_File_Names.C_Lex_Unit_Name & ";");
      New_Line (The_Ada_File);
      New_Line (The_Ada_File);
      Put_Line
        (The_Ada_File,
         "package body " & Ayacc_File_Names.C_Lex_Unit_Name & " is");
      New_Line (The_Ada_File);
      Put_Line (The_Ada_File, "    function Get_Token return Integer;");
      New_Line (The_Ada_File);
      Put_Line (The_Ada_File, "    pragma Interface(C, Get_Token);");
      New_Line (The_Ada_File);
      Put_Line (The_Ada_File, "    type Table is array(0..255) of Token;");
      Put_Line (The_Ada_File, "    Literals : constant Table := Table'(");
      Put_Line (The_Ada_File, "        0 => END_OF_INPUT,");

      Create
        (The_Define_File, Out_File, Ayacc_File_Names.Get_Include_File_Name);

      Put_Line
        (The_Define_File,
         "/* C_Lex Token Definition for type " &
         Ayacc_File_Names.Tokens_Unit_Name & ".Token; */");
      New_Line (The_Define_File);

      for I in First_Symbol (Terminal) .. Last_Symbol (Terminal) loop
         Sym_Name := Convert (Get_Symbol_Name (I));
         if Sym_Name.Name (1) /= ''' then
            Put (The_Define_File, "#define ");
            Put (The_Define_File, Sym_Name.Name (1 .. Sym_Name.Length));
            Put_Line (The_Define_File, "  " & Grammar_Symbol'Image (I + 256));
         else
            Put
              (The_Ada_File,
               "       " & Integer'Image (Character'Pos (Sym_Name.Name (2))) &
               " => ");
            Put (The_Ada_File, Sym_Name.Name (1 .. Sym_Name.Length) & ',');
            New_Line (The_Ada_File);
         end if;
      end loop;

      Put_Line (The_Ada_File, "        others => Error); ");
      New_Line (The_Ada_File);

      Put_Line (The_Ada_File, "    function YYLex return Token is");
      Put_Line (The_Ada_File, "        Token_Value : Integer;");
      Put_Line (The_Ada_File, "    begin");
      Put_Line (The_Ada_File, "        Token_Value := Get_Token;");
      Put_Line (The_Ada_File, "        if Token_Value > 255 then");
      Put_Line
        (The_Ada_File, "            return Token'Val(Token_Value-256);");
      Put_Line (The_Ada_File, "        else                        ");
      Put_Line
        (The_Ada_File, "            return Literals(Token_Value);     ");
      Put_Line (The_Ada_File, "        end if; ");
      Put_Line (The_Ada_File, "    end YYLex; ");

      Put_Line (The_Ada_File, "end " & Ayacc_File_Names.C_Lex_Unit_Name & ";");
      Close (The_Ada_File);
      Close (The_Define_File);
   end Make_C_Lex_Package;

end Tokens_File;
