|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T
Length: 410339 (0x642e3)
Types: TextFile
Names: »TOUT«
└─⟦a7d1ea751⟧ Bits:30000550 8mm tape, Rational 1000, !users!projects 94_04_11
└─⟦129cab021⟧ »DATA«
└─⟦this⟧
└─⟦2f6cfab89⟧ Bits:30000547 8mm tape, Rational 1000, !projects 94-01-04
└─⟦d65440be7⟧ »DATA«
└─⟦this⟧
-- 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 : actions_file.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:27:44
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxactions_file.ada
-- $Header: actions_file.a,v 0.1 86/04/01 15:03:51 ada Exp $
-- $Log: actions_file.a,v $
-- Revision 0.1 86/04/01 15:03:51 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:35:43 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 Text_IO; use Text_IO;
package Actions_File is
-- --
-- Standard file access routines for the file containing --
-- the procedure user_action which associates rules to the --
-- user executable code. --
-- --
type File_Mode is (Read_File, Write_File);
procedure Open(Mode: in File_Mode);
procedure Write(C: in Character);
procedure Write(S: in String);
procedure Writeln;
procedure Read_Line(S: out String; Last: out Natural);
procedure Close;
procedure Delete;
-- Initializes and finishes the decalarations for the --
-- procedure user_action. --
procedure Initialize;
procedure Finish;
function Is_End_of_File return Boolean;
end Actions_File;
-- 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 : actions_file_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:28:04
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxactions_file_body.ada
-- $Header: actions_file_body.a,v 0.1 86/04/01 15:29:59 ada Exp $
-- $Log: actions_file_body.a,v $
--Revision 0.1 86/04/01 15:29:59 ada
-- This version fixes some minor bugs with empty grammars
-- and $$ expansion. It also uses vads5.1b enhancements
-- such as pragma inline.
--
with File_Names;
use File_Names;
package body Actions_File is
SCCS_ID : constant String := "@(#) actions_file_body.ada, Version 1.2";
-- The maximum length of the text that an action can expand into.
Maximum_Action_Length : constant Count := 1000;
The_File : File_Type;
procedure Open(Mode: in File_Mode) is
begin
if Mode = Read_File then
Open(The_File, In_File, Get_Actions_File_Name);
else
Create(The_File, Out_File, Get_Actions_File_Name);
--RJS Set_Line_Length(The_File, To => Maximum_Action_Length);
end if;
end Open;
procedure Close is
begin
Close(The_File);
end Close;
procedure Delete is
begin
Delete(The_File);
end Delete;
procedure Read_Line(S: out String; Last: out Natural) is
begin
Get_Line(The_File, S, Last);
end;
procedure Write(S: in String) is
begin
Put(The_File, S);
end;
procedure Write(C: in Character) is
begin
Put(The_File, C);
end;
procedure Writeln is
begin
New_Line(The_File);
end;
function Is_End_of_File return Boolean is
begin
return End_of_File(The_File);
end Is_End_of_File;
procedure Initialize is
begin
Open(Write_File);
end Initialize;
procedure Finish is
begin
Close;
end Finish;
end Actions_File;
-- 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.
--************************************************************************
-- ayacc
-- version 1.0
--
--***********************************************************************
--
-- Arcadia Project
-- Department of Information and Computer Science
-- University of California
-- Irvine, California 92717
--
--***************************************************************************
-- Module : ayacc.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:28:24
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxayacc.ada
-- $Header: ayacc.a,v 0.1 86/04/01 15:04:07 ada Exp $
-- $Log: ayacc.a,v $
-- Revision 0.1 86/04/01 15:04:07 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 19:00:49 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 Source_File,
File_Names,
Options,
Parser,
Tokens_File,
Output_File,
Parse_Table,
Text_IO,
-- u_env, -- For getting the command line arguments
Symbol_Table, -- Used for statistics only
Rule_Table; -- Used for statistics only
procedure Ayacc is
Rcs_ID : constant String := "$Header: ayacc.a,v 0.1 86/04/01 15:04:07 ada Exp $";
copyright : constant string :=
"@(#) Copyright (c) 1990 Regents of the University of California.";
copyright2 : constant string :=
"All rights reserved.";
use Text_IO;
Illegal_Argument_List : exception;
procedure Initialize is separate;
procedure Print_Statistics is separate;
begin
Initialize;
Source_File.Open;
Tokens_File.Open;
Parser.Parse_Declarations;
Parser.Parse_Rules;
Parse_Table.Make_Parse_Table;
Output_File.Make_Output_File;
Tokens_File.Complete_Tokens_Package;
Source_File.Close;
Tokens_File.Close;
if Options.Interface_to_C then
Tokens_File.Make_C_Lex_Package;
end if;
Print_Statistics;
exception
when File_Names.Illegal_File_Name =>
Put_Line("Ayacc: Illegal Filename.");
when Options.Illegal_Option | Illegal_Argument_List =>
null;
when Parser.Syntax_Error => -- Error has already been reported.
Source_File.Close;
when Text_IO.Name_Error | Text_IO.Use_Error =>
null; -- Error has already been reported.
when others =>
Put_Line ("Ayacc: Internal Error, Please Submit an LCR.");
end Ayacc;
-- 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 : ayacc_separates.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:28:51
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxayacc_separates.ada
-- $Header: ayacc_separates.a,v 0.0 86/02/19 18:36:14 ada Exp $
-- $Log: ayacc_separates.a,v $
-- Revision 0.0 86/02/19 18:36:14 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.
--
-- Revision 0.1 88/03/16
-- Additional argument added to allow user to specify file extension
-- to be used for generated Ada files. -- kn
with String_Pkg; use String_Pkg;
separate (Ayacc)
procedure Initialize is
use File_Names, Options;
Input_File, Extension, Options : String_Type := Create ("");
type Switch is ( On , Off );
C_Lex_Flag,
Debug_Flag,
Summary_Flag,
Verbose_Flag : Switch;
Invalid_Command_Line : exception;
procedure Get_Arguments (File : out String_Type;
C_Lex : out Switch;
Debug : out Switch;
Summary : out Switch;
Verbose : out Switch;
Extension : out String_Type) is separate;
begin
Get_Arguments (Input_File,
C_Lex_Flag,
Debug_Flag,
Summary_Flag,
Verbose_Flag,
Extension);
New_Line;
Put_Line (" Ayacc (File => """ & Value (Input_File) & """,");
Put_Line (" C_Lex => " &
Value (Mixed (Switch'Image(C_Lex_Flag))) & ',');
Put_Line (" Debug => " &
Value (Mixed (Switch'Image(Debug_Flag))) & ',');
Put_Line (" Summary => " &
Value (Mixed (Switch'Image(Summary_Flag))) & ',');
Put_Line (" Verbose => " &
Value (Mixed (Switch'Image(Verbose_Flag))) & ",");
Put_Line (" Extension => """ & Value (Extension) & """);");
New_Line;
if C_Lex_Flag = On then
Options := Options & Create ("i");
end if;
if Debug_Flag = On then
Options := Options & Create ("d");
end if;
if Summary_Flag = On then
Options := Options & Create ("s");
end if;
if Verbose_Flag = On then
Options := Options & Create ("v");
end if;
Set_File_Names (Value (Input_File), Value(Extension));
Set_Options (Value (Options));
exception
when Invalid_Command_Line =>
raise Illegal_Argument_List;
end Initialize;
separate (Ayacc)
procedure Print_Statistics is
use Text_IO, Parse_Table, Rule_Table, Symbol_Table;
begin
if Options.Summary then
Put_Line(Rule'Image(Last_Rule - First_Rule + 1) & " Productions");
Put_Line(Grammar_Symbol'Image
(Last_Symbol(Nonterminal) - First_Symbol(Nonterminal) + 1) &
" Nonterminals");
Put_Line(Grammar_Symbol'Image
(Last_Symbol(Terminal) - First_Symbol(Terminal) + 1) &
" Terminals");
Put_Line(Integer'Image(Number_of_States) & " States");
Put_Line (Integer'Image(Shift_Reduce_Conflicts) &
" Shift/Reduce conflicts");
Put_Line (Integer'Image(Reduce_Reduce_Conflicts) &
" Reduce/Reduce conflicts");
else
if Shift_Reduce_Conflicts /= 0 then
Put_Line (Integer'Image(Shift_Reduce_Conflicts) &
" Shift/Reduce Conflicts");
end if;
if Reduce_Reduce_Conflicts /= 0 then
Put_Line (Integer'Image(Reduce_Reduce_Conflicts) &
" Reduce/Reduce Conflicts");
end if;
end if;
end Print_Statistics;
with Command_Line_Interface; use Command_Line_Interface;
with String_Pkg; use String_Pkg;
--VAX with Vms_Lib;
separate (Ayacc.Initialize)
procedure Get_Arguments (File : out String_Type;
C_Lex : out Switch;
Debug : out Switch;
Summary : out Switch;
Verbose : out Switch;
Extension : out String_Type) is
C_Lex_Argument : String_Type;
Debug_Argument : String_Type;
Summary_Argument : String_Type;
Verbose_Argument : String_Type;
Positional : Natural := 0;
-- Number of positional parameters
Total : Natural := 0;
-- Total number of parameters
Max_Parameters : constant := 6;
Incorrect_Call : exception;
function Convert_Switch is new
Convert (Parameter_Type => Switch,
Type_Name => "Switch");
procedure Put_Help_Message is
begin
New_Line;
Put_Line (" -- Ayacc: An Ada Parser Generator.");
New_Line;
Put_Line (" type Switch is (On, Off);");
New_Line;
Put_Line (" procedure Ayacc (File : in String;");
Put_Line (" C_Lex : in Switch := Off;");
Put_Line (" Debug : in Switch := Off;");
Put_Line (" Summary : in Switch := On;");
Put_Line (" Verbose : in Switch := Off;");
Put_Line (" Extension : in String := "".a"");");
New_Line;
Put_Line (" -- File Specifies the Ayacc Input Source File.");
Put_Line (" -- C_Lex Specifies the Generation of a 'C' Lex Interface.");
Put_Line (" -- Debug Specifies the Production of Debugging Output");
Put_Line (" -- By the Generated Parser.");
Put_Line (" -- Summary Specifies the Printing of Statistics About the");
Put_Line (" -- Generated Parser.");
Put_Line (" -- Verbose Specifies the Production of a Human Readable");
Put_Line (" -- Report of States in the Generated Parser.");
Put_Line (" -- Extension Specifies the file extension to be used for");
Put_Line (" generated Ada files.");
New_Line;
end Put_Help_Message;
begin
--VAX Vms_Lib.Set_Error;
Command_Line_Interface.Initialize (Tool_Name => "Ayacc");
Positional := Positional_Arg_Count;
Total := Named_Arg_Count + Positional;
if Total = 0 then
raise Incorrect_Call;
elsif Total > Max_Parameters then
Put_Line ("Ayacc: Too many parameters.");
raise Incorrect_Call;
end if;
-- Get named values
File := Named_Arg_Value ("File", "");
C_Lex_Argument := Named_Arg_Value ("C_Lex", "Off");
Debug_Argument := Named_Arg_Value ("Debug", "Off");
Summary_Argument := Named_Arg_Value ("Summary", "On");
Verbose_Argument := Named_Arg_Value ("Verbose", "Off");
Extension := Named_Arg_Value ("Extension", ".a");
-- Get any positional associations
if Positional >= 1 then
File := Positional_Arg_Value (1);
if Positional >= 2 then
C_Lex_Argument := Positional_Arg_Value (2);
if Positional >= 3 then
Debug_Argument := Positional_Arg_Value (3);
if Positional >= 4 then
Summary_Argument := Positional_Arg_Value (4);
if Positional >= 5 then
Verbose_Argument := Positional_Arg_Value (5);
if Positional = Max_Parameters then
Extension := Positional_Arg_Value (Max_Parameters);
end if;
end if;
end if;
end if;
end if;
end if;
Command_Line_Interface.Finalize;
C_Lex := Convert_Switch (Value (C_Lex_Argument));
Debug := Convert_Switch (Value (Debug_Argument));
Summary := Convert_Switch (Value (Summary_Argument));
Verbose := Convert_Switch (Value (Verbose_Argument));
exception
when Incorrect_Call | Invalid_Parameter |
Invalid_Parameter_Order | Missing_Positional_Arg |
Unreferenced_Named_Arg | Invalid_Named_Association |
Unbalanced_Parentheses =>
Put_Help_Message ;
raise Invalid_Command_Line ;
end Get_Arguments;
-- 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.
--|
--| Notes: This routine contains the machine specific details of how
--| Ayacc obtains the command line arguments from the host Operating
--| System. This version assumes Verdix running on Unix machines.
--|
--| The only requirement on this subunit is that it place the string
--| of characters typed by the user on the command line into the
--| parameter "Command_Args".
--|
with A_Strings; use A_Strings;
with U_Env; use U_Env;
separate (Command_Line_Interface)
procedure Read_Command_Line (Command_Args : out Command_Line_Type) is
Unix_Command_Line : A_String := Empty;
begin
for i in Argv.all'First + 1 .. Argv.all'Last
loop
Unix_Command_Line := Unix_Command_Line & Argv (i) & " ";
end loop;
Unix_Command_Line := Pad_Right (Unix_Command_Line,
To_Length => Maximum_Command_Length);
Command_Args := Unix_Command_Line.S;
end Read_Command_Line;
-- 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 : command_line_interface.ada
-- Component of : common_library
-- Version : 1.2
-- Date : 11/21/86 16:02:24
-- SCCS File : disk21~/rschm/hasee/sccs/common_library/sccs/sxcommand_line_interface.ada
with Text_IO; use Text_IO;
with String_scanner;
----------------------------------------------------------------
Package body command_line_interface is
SCCS_ID : constant String := "@(#) command_line_interface.addisk21~/rschm/hasee/sccs/common_library, Version 1.2";
--| Provides primitives for getting at the command line arguments.
--| Overview
Package sp renames String_pkg;
Package ss renames String_scanner;
type Name_value is --| Name/Value pair
record
Name: sp.String_type; --| Name of value
Value: sp.String_type; --| Value associated with name
Was_retrieved: boolean:=FALSE; --| Flag indicating whether name-value
end record; -- association has been retrieved by tool
type Token_type is (Ada_ID,Word,Bound_to,None);
Package Token_type_IO is new Enumeration_IO(Token_type);
use Token_type_IO;
Maximum_Command_Length : constant := 1024;
subtype Command_Line_Type is String (1 .. Maximum_Command_Length);
Arg_string : Command_Line_Type; --| String obtained from operating system
N_arg_count: Argument_count; --| Count of named args
P_arg_count: Argument_count; --| Count of positional args
Rejected: boolean := FALSE;
Tool_Name : String_Type;
Named_args: array(argument_index)
of Name_value;
Positional_args: array(argument_index)
of sp.String_type;
procedure Read_Command_Line
(Command_Args : out Command_Line_Type) is separate;
--**
--| Description: Read_Command_Line is the machine dependent interface to
--| the Operating System Command Line.
--**
----------------------------------------------------------------
-- Local functions:
procedure Set_Tool_Name (To : in String) is
begin
Tool_Name := Create (To & ": ");
end Set_Tool_Name;
procedure CLI_Error (Error_Message : in String) is
begin
New_Line;
Put_Line (Value (Tool_Name) & Error_Message);
end CLI_Error;
procedure Get_token(
Scan_string : in out ss.Scanner;
Argument : in out sp.String_type;
Kind: in out Token_type
) is
Last_arg: sp.String_type;
Last_kind: Token_type;
Found: boolean;
Delimeter: sp.String_type;
Delim_string: ss.Scanner;
More_commas: boolean := FALSE;
Tail: sp.String_type;
begin
if Rejected then
Argument := Last_arg;
Kind := Last_kind;
Rejected := FALSE;
else
if ss.Is_sequence(" ,",Scan_string) then
ss.Scan_sequence(" ,",Scan_string,Found,Delimeter);
Delim_string := ss.Make_scanner(Delimeter);
loop
ss.Skip_space(Delim_string);
exit when not ss.More(Delim_string);
ss.Forward(Delim_string);
if More_commas then
CLI_Error ("Missing Positional Argument.");
raise missing_positional_arg;
end if;
More_commas := TRUE;
end loop;
end if;
if ss.Is_Ada_Id(Scan_string) then
ss.Scan_Ada_Id(Scan_string,Found,Argument);
if ss.Is_Literal("=>",Scan_string) or
ss.Is_Literal("""",Scan_string) or
ss.Is_sequence(" ,",Scan_string) or
not ss.More(Scan_string) then
Kind := Ada_ID;
else
if ss.Is_not_sequence(" ,",Scan_string) then
ss.Scan_not_sequence(" ,",Scan_string,Found,Tail);
Argument := sp."&"(Argument,Tail);
Kind := Word;
else
ss.Scan_word(Scan_string,Found,Tail);
Argument := sp."&"(Argument,Tail);
Kind := Word;
end if;
end if;
elsif ss.Is_Literal("=>",Scan_string) then
ss.Scan_Literal("=>",Scan_string,Found);
Argument := sp.Create("=>");
Kind := Bound_to;
elsif ss.Is_quoted(Scan_string) then
ss.Scan_quoted(Scan_string,Found,Argument);
Kind := Word;
elsif ss.Is_enclosed('(',')',Scan_string) then
ss.Scan_enclosed('(',')',Scan_string,Found,Argument);
Kind := Word;
elsif ss.Is_not_sequence(" ,",Scan_string) then
ss.Scan_not_sequence(" ,",Scan_string,Found,Argument);
Kind := Word;
elsif ss.Is_word(Scan_string) then
ss.Scan_word(Scan_string,Found,Argument);
Kind := Word;
else
Argument := sp.Create("");
Kind := None;
end if;
Last_kind := Kind;
Last_arg := Argument;
end if;
end Get_token;
-----------------------------------------------------------------------
procedure Save_named(
Name : in sp.String_type;
Value : in sp.String_type
) is
begin
N_arg_count := N_arg_count + 1;
Named_args(N_arg_count).Name := Name;
Named_args(N_arg_count).Value := Value;
end Save_named;
procedure Save_positional(
Value : in sp.String_type
) is
begin
if N_arg_count > 0 then
CLI_Error ("Invalid Parameter Order, " &
"Positional arguments must precede Named.");
raise invalid_parameter_order;
end if;
P_arg_count := P_arg_count + 1;
Positional_args(P_arg_count) := Value;
end Save_positional;
procedure Reject_token is
begin
Rejected := TRUE;
end Reject_token;
----------------------------------------------------------------
procedure Initialize (Tool_Name : in String) is
begin
Set_Tool_Name (To => Tool_Name);
declare
type State_type is (Have_nothing,Have_Ada_ID,Have_bound_to);
Start_Index : integer; --|
End_Index: integer; --| Indices of characters in argument string
Scan_string: ss.Scanner; --| Scanned argument string
Argument: sp.String_Type; --| Argument scanned from argument string
Kind: Token_type; --| Kind of argument- WORD, =>, Ada_ID
Old_arg: sp.String_Type; --| Previously scanned argument
Found: boolean;
State: State_type := Have_nothing;
--| State of argument in decision tree
begin
Start_Index := Arg_string'first;
End_Index := Arg_string'first;
N_arg_count := 0;
P_arg_count := 0;
-- Get the command line from the operating system
Read_Command_Line (Arg_String);
-- Remove trailing blanks and final semicolon
for i in reverse Arg_string'range loop
if Arg_string(i) /= ' ' then
if Arg_string(i) = ';' then
End_Index := i - 1;
else
End_Index := i;
end if;
exit;
end if;
end loop;
Skip_Leading_White_Space :
for i in Arg_String'First .. End_Index
loop
if Arg_String (i) /= ' ' and then
Arg_String (i) /= Ascii.HT then
Start_Index := i;
exit Skip_Leading_White_Space;
end if;
end loop Skip_Leading_White_Space;
Verify_Balanced_Parentheses :
declare
Left_Parens : Natural := 0;
Right_Parens : Natural := 0;
begin
for i in Start_Index .. End_Index
loop
if Arg_String (i) = '(' then
Left_Parens := Left_Parens + 1;
elsif Arg_String (i) = ')' then
Right_Parens := Right_Parens + 1;
end if;
end loop;
if Left_Parens /= Right_Parens then
CLI_Error ("Unbalanced Parentheses.");
raise Unbalanced_Parentheses;
end if;
end Verify_Balanced_Parentheses;
-- Convert argument string to scanner and remove enclosing parantheses
Scan_string := ss.Make_scanner(sp.Create(
Arg_string(Start_Index .. End_Index)));
if ss.Is_enclosed('(',')',Scan_string) then
ss.Mark(Scan_string);
ss.Scan_enclosed('(',')',Scan_string,Found,Argument);
ss.Skip_Space(Scan_string);
if not ss.More(Scan_string) then
ss.Destroy_Scanner(Scan_string);
Scan_string := ss.Make_scanner(Argument);
else
ss.Restore(Scan_string);
end if;
end if;
-- Parse argument string and save arguments
loop
Get_token(Scan_string,Argument,Kind);
case State is
when Have_nothing =>
case Kind is
when Ada_ID =>
Old_arg := Argument;
State := Have_Ada_ID;
when Word =>
Save_positional(Argument);
State := Have_nothing;
when Bound_to =>
State := Have_nothing;
CLI_Error ("Invalid Named Association.");
raise invalid_named_association;
when None =>
null;
end case;
when Have_Ada_ID =>
case Kind is
when Ada_ID =>
Save_positional(Old_arg);
Old_arg := Argument;
State := Have_Ada_ID;
when Word =>
Save_positional(Old_arg);
Save_positional(Argument);
State := Have_nothing;
when Bound_to =>
State := Have_bound_to;
when None =>
Save_positional(Old_arg);
end case;
when Have_bound_to =>
case Kind is
when Ada_ID | Word =>
Save_named(Old_arg,Argument);
State := Have_nothing;
when Bound_to =>
State := Have_bound_to;
CLI_Error ("Invalid Named Association.");
raise invalid_named_association;
when None =>
CLI_Error ("Invalid Named Association.");
raise invalid_named_association;
end case;
end case;
exit when Kind = None;
end loop;
end;
end Initialize;
--------------------------------------------------------------------------
function Named_arg_count --| Return number of named arguments
return Argument_count is
begin
return N_arg_count;
end;
----------------------------------------------------------------
function Positional_arg_count --| Return number of positional arguments
return Argument_count is
begin
return P_arg_count;
end;
----------------------------------------------------------------
function Positional_arg_value( --| Return an argument value
N: Argument_index --| Position of desired argument
) return string is --| Raises: no_arg
--| Effects: Return the Nth argument. If there is no argument at
--| position N, no_arg is raised.
--| N/A: modifies, errors
begin
if N > P_arg_count then
CLI_Error ("Internal Error, Argument" & Argument_Index'Image (N) &
" does not exist. Please submit an LCR.");
raise no_arg;
else
return sp.Value(Positional_args(N));
end if;
end;
----------------------------------------------------------------
function Positional_arg_value( --| Return an argument value
N: Argument_index --| Position of desired argument
) return sp.String_type is --| Raises: no_arg
--| Effects: Return the Nth argument. If there is no argument at
--| position N, no_arg is raised.
--| N/A: modifies, errors
begin
if N > P_arg_count then
CLI_Error ("Internal Error, Argument" & Argument_Index'Image (N) &
" does not exist. Please submit an LCR.");
raise no_arg;
else
return Positional_args(N);
end if;
end;
----------------------------------------------------------------
function Named_arg_value(--| Return a named argument value
Name: string;
Default: string
) return string is
--| Effects: Return the value associated with Name on the command
--| line. If there was none, return Default.
begin
for i in 1..N_arg_count
loop
if sp.Equal(sp.Upper(Named_args(i).Name),sp.Upper(sp.Create(Name))) then
Named_args(i).Was_retrieved := TRUE;
return sp.Value(Named_args(i).Value);
end if;
end loop;
return Default;
end;
function Named_arg_value(--| Return a named argument value
Name: string;
Default: string
) return String_Type is
--| Effects: Return the value associated with Name on the command
--| line. If there was none, return Default.
begin
return Create (Named_Arg_Value (Name, Default));
end Named_Arg_Value;
----------------------------------------------------------------
function Named_arg_value(--| Return a named argument value
Name: string;
Default: sp.String_type
) return sp.String_type is
--| Effects: Return the value associated with Name on the command
--| line. If there was none, return Default.
begin
for i in 1..N_arg_count
loop
if sp.Equal(sp.Upper(Named_args(i).Name),sp.Upper(sp.Create(Name))) then
Named_args(i).Was_retrieved := TRUE;
return Named_args(i).Value;
end if;
end loop;
return Default;
end;
----------------------------------------------------------------
function Arguments --| Return the entire argument string
return string is
--| Effects: Return the entire command line, except for the name
--| of the command itself.
begin
return Arg_string;
end;
----------------------------------------------------------------
function Parse_Aggregate (Aggregate_Text : in String)
return String_Lists.List is
type State_type is (Have_Nothing,
Have_Ada_ID,
Have_Bound_To);
First : Natural := Aggregate_Text'First;
Last : Natural := Aggregate_Text'Last;
Component_List : String_Lists.List := String_Lists.Create;
Argument : sp.String_Type; --| Argument scanned from argument string
Kind : Token_type; --| Kind of argument- WORD, =>, Ada_ID
Scan_string : ss.Scanner; --| Scanned argument string
Aggregate_Contents : String_Type;
Enclosed_Aggregate_Found : Boolean := False;
begin
if Aggregate_Text'Length > 0 then
Scan_String := SS.Make_Scanner (Create (Aggregate_Text (First .. Last)));
SS.Scan_Enclosed ( '(', ')',
Scan_String,
Found => Enclosed_Aggregate_Found,
Result => Aggregate_Contents,
Skip => True);
if Enclosed_Aggregate_Found then
SS.Destroy_Scanner (Scan_String);
Scan_String := SS.Make_Scanner (Aggregate_Contents);
end if;
Parse_Aggregate_String :
loop
Get_token(Scan_string, Argument, Kind);
exit Parse_Aggregate_String when Kind = None;
String_Lists.Attach (Component_List, Argument);
end loop Parse_Aggregate_String;
end if;
return Component_List;
end Parse_Aggregate;
function Parse_Aggregate
(Aggregate_Text : in String_Type)
return String_Lists.List is
begin
return Parse_Aggregate (Value (Aggregate_Text));
end Parse_Aggregate;
----------------------------------------------------------------
function Convert (Parameter_Text : in String) return Parameter_Type is
begin
return Parameter_Type'Value (Parameter_Text);
exception
when Constraint_Error =>
CLI_Error ("Invalid Parameter, """ &
Value (Mixed (Parameter_Text)) &
""" is not a legal value for type " &
Value (Mixed (Type_Name)) & '.');
raise Invalid_Parameter;
end Convert;
----------------------------------------------------------------
procedure Finalize is --| Raises: unreferenced_named_arg
begin
for i in 1..Named_arg_count loop
if Named_args(i).Was_retrieved = FALSE then
CLI_Error ("Invalid Parameter Association, " &
Value (Mixed (Named_Args (i).Name)) &
" is not a valid Formal Parameter.");
raise unreferenced_named_arg;
end if;
end loop;
end Finalize;
-------------------------------------------------------------------
end command_line_interface;
-- 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 : command_line_interface_.ada
-- Component of : common_library
-- Version : 1.2
-- Date : 11/21/86 16:03:08
-- SCCS File : disk21~/rschm/hasee/sccs/common_library/sccs/sxcommand_line_interface_.ada
with String_Lists; use String_Lists;
with String_pkg; use String_pkg;
--------------------------------------------------------------------
Package command_line_interface is
--| Provides primitives for getting at the command line arguments.
--| Overview
--| This package provides a universal and portable interface to
--| the arguments typed on a command line when a program is invoked.
--| Each command line argument is either a Word (sequence of non-blank
--| characters) or a quoted string, with embedded quotes doubled.
--|
--| Both named and positional arguments may be given on the command
--| line. However, once a named parameter is used, all the subseqent
--| parameters on the command line must be named parameters. For example,
--| the commands
--|-
--| compile abc pqr xyz library => plib
--| compile abc,pqr,unit=>xyz,library=>plib
--|+
--| have one named argument and three positional arguments. This
--| package separates the named parameters from the positional
--| parameters, ignores spaces around the "bound to" (=>) symbol, and
--| allows parameters to be separated by either spaces or commas,
--| so these command lines are indistinguishable.
--|
--| At program elaboration time, the command line string is automatically
--| obtained from the host operating system and parsed into
--| individual arguments. The following operations may then be used:
--|-
--| Named_arg_count() Returns number of named arguments entered
--| Positional_arg_count() Returns number of positional arguments
--| Positional_arg_value(N) Returns the Nth positional argument
--| Named_arg_value(Name, Dflt) Returns value of a named argument
--| Arguments() Returns the entire command line
--|+
----------------------------------------------------------------
max_args: constant := 255;
--| Maximum number of command line arguments (arbitrary).
subtype Argument_count is integer range 0..max_args;
--| For number of arguments
subtype Argument_index is Argument_count range 1..Argument_count'last;
--| Used to number the command line arguments.
no_arg: exception;
--| Raised when request made for nonexistent argument
missing_positional_arg: exception;
--| Raised when command line is missing positional argument (A,,B)
invalid_named_association: exception;
--| Raised when command line is missing named argument value (output=> ,A,B)
unreferenced_named_arg: exception;
--| Raised when not all named parameters have been retrieved
invalid_parameter_order: exception;
--| Raised when a positional parameter occurs after a named parameter
-- in the command line
--Invalid_Aggregate : exception;
--| Raised when an aggregate does not begin and end with parentheses
-- in Parse_Aggregate.
Unbalanced_Parentheses : exception;
--| Raised when the number of left paren's does not match the number
--| of right paren's.
Invalid_Parameter : exception;
--| Raised when the conversion of a string to a parameter type is not
--| possible.
----------------------------------------------------------------
procedure Initialize (Tool_Name : in String);
--| Initializes command_line_interface
--| N/A: modifies, errors, raises
---------------------------------------------------------------------
function Named_arg_count --| Return number of named arguments
return Argument_count;
--| N/A: modifies, errors, raises
function Positional_arg_count --| Return number of positional arguments
return Argument_count;
--| N/A: modifies, errors, raises
----------------------------------------------------------------
function Positional_arg_value( --| Return an argument value
N: Argument_index --| Position of desired argument
) return string; --| Raises: no_arg
--| Effects: Return the Nth argument. If there is no argument at
--| position N, no_arg is raised.
--| N/A: modifies, errors
function Positional_arg_value( --| Return an argument value
N: Argument_index --| Position of desired argument
) return String_type; --| Raises: no_arg
--| Effects: Return the Nth argument. If there is no argument at
--| position N, no_arg is raised.
--| N/A: modifies, errors
--------------------------------------------------------------------
function Named_arg_value(--| Return a named argument value
Name: string;
Default: string
) return string;
--| Effects: Return the value associated with Name on the command
--| line. If there was none, return Default.
--| N/A: modifies, errors
function Named_arg_value(--| Return a named argument value
Name: string;
Default: string
) return String_Type;
--| Effects: Return the value associated with Name on the command
--| line. If there was none, return Default.
--| N/A: modifies, errors
function Named_arg_value(--| Return a named argument value
Name: string;
Default: String_type
) return String_type;
--| Effects: Return the value associated with Name on the command
--| line. If there was none, return Default.
--| N/A: modifies, errors
----------------------------------------------------------------
function Arguments --| Return the entire argument string
return string;
--| Effects: Return the entire command line, except for the name
--| of the command itself.
--| N/A: modifies, errors, raises
----------------------------------------------------------------
function Parse_Aggregate (Aggregate_Text : in String_Type)
return String_Lists.List;
function Parse_Aggregate (Aggregate_Text : in String)
return String_Lists.List;
--| Effects: Returns components of Aggregate_Text as a String_List.
--| Raises : Invalid_Aggregate
----------------------------------------------------------------
generic
type Parameter_Type is (<>);
Type_Name : in String;
function Convert (Parameter_Text : in String) return Parameter_Type;
--| Raises: Invalid_Parameter
----------------------------------------------------------------
procedure Finalize ; --| Raises: unrecognized parameters
--| Effects: If not all named parameters have been retrieved
--| unrecognized parameters is raised.
--| N/A: modifies, errors
end command_line_interface;
----------------------------------------------------------------
-- 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 : file_names.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:29:16
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxfile_names.ada
-- $Header: file_names.a,v 0.1 86/04/01 15:04:19 ada Exp $
-- $Log: file_names.a,v $
-- Revision 0,2 88/03/16
-- Set file names modified to include a file extension parameter.
-- Revision 0.1 86/04/01 15:04:19 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:36:22 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.
--
-- The collection of all file names used by Ayacc --
package File_Names is
procedure Set_File_Names(Input_File, Extension: in String);
-- Sets the initial value of the file names
-- according to the INPUT_FILE.
function Get_Source_File_Name return String;
function Get_Out_File_Name return String;
function Get_Verbose_File_Name return String;
function Get_Template_File_Name return String;
function Get_Actions_File_Name return String;
function Get_Shift_Reduce_File_Name return String;
function Get_Goto_File_Name return String;
function Get_Tokens_File_Name return String;
function Get_C_Lex_File_Name return String;
function Get_Include_File_Name return String;
--RJS ==========================================
function C_Lex_Unit_Name return String;
function Goto_Tables_Unit_Name return String;
function Shift_Reduce_Tables_Unit_Name return String;
function Tokens_Unit_Name return String;
--RJS ==========================================
Illegal_File_Name: exception;
-- Raised if the file name does not end with ".y"
end File_Names;
with STR_Pack;
use STR_Pack;
with String_Pkg;
package body File_Names is
SCCS_ID : constant String := "@(#) file_names.ada, Version 1.2";
Rcs_ID : constant String := "$Header: file_names.a,v 0.1 86/04/01 15:04:19 ada Exp $";
Max_Name_Length : constant := 50;
Source_File_Name : STR(Max_Name_Length);
Out_File_Name : STR(Max_Name_Length);
Verbose_File_Name : STR(Max_Name_Length);
Template_File_Name : STR(Max_Name_Length);
Actions_File_Name : STR(Max_Name_Length);
Shift_Reduce_File_Name : STR(Max_Name_Length);
Goto_File_Name : STR(Max_Name_Length);
Tokens_File_Name : STR(Max_Name_Length);
C_Lex_File_Name : STR(Max_Name_Length);
Include_File_Name : STR(Max_Name_Length);
--RJS ==========================================
function End_of_Unit_Name (Name : in String) return Natural is
Dot_Position : Natural := Name'Last;
begin
while Dot_Position >= Name'First and then
Name (Dot_Position) /= '.'
loop
Dot_Position := Dot_Position - 1;
end loop;
return Dot_Position - 1;
end End_of_Unit_Name;
function Get_Unit_Name (Filename : in String) return String is
Filename_Without_Extension : constant String :=
Filename (Filename'First .. End_of_Unit_Name (Filename));
End_of_Directory : Natural := Filename_Without_Extension'Last;
function Character_Is_Part_of_Unit_Name (Ch : in Character) return Boolean is
begin
return Ch in 'A' .. 'Z' or else
Ch in 'a' .. 'z' or else
Ch = '_';
end Character_Is_Part_of_Unit_Name;
use String_Pkg;
begin
while End_of_Directory >= Filename_Without_Extension'First and then
Character_Is_Part_of_Unit_Name (
Filename_Without_Extension (End_of_Directory))
loop
End_of_Directory := End_of_Directory - 1;
end loop;
return Value (Mixed (Filename_Without_Extension (End_of_Directory + 1 ..
Filename_Without_Extension'Last)));
end Get_Unit_Name;
function C_Lex_Unit_Name return String is
Filename : constant String := Value_of (Upper_Case (C_Lex_File_Name));
begin
return Get_Unit_Name (Filename);
end C_Lex_Unit_Name;
function Goto_Tables_Unit_Name return String is
Filename : constant String := Value_of (Upper_Case (Goto_File_Name));
begin
return Get_Unit_Name (Filename);
end Goto_Tables_Unit_Name;
function Shift_Reduce_Tables_Unit_Name return String is
Filename : constant String := Value_of (Upper_Case (Shift_Reduce_File_Name));
begin
return Get_Unit_Name (Filename);
end Shift_Reduce_Tables_Unit_Name;
function Tokens_Unit_Name return String is
Filename : constant String := Value_of (Upper_Case (Tokens_File_Name));
begin
return Get_Unit_Name (Filename);
end Tokens_Unit_Name;
--RJS ==========================================
function Get_Source_File_Name return String is
begin
return Value_of(Source_File_Name);
end;
function Get_Out_File_Name return String is
begin
return Value_of(Out_File_Name);
end;
function Get_Verbose_File_Name return String is
begin
return Value_of(Verbose_File_Name);
end;
function Get_Template_File_Name return String is
begin
return Value_of(Template_File_Name);
end;
function Get_Actions_File_Name return String is
begin
return Value_of(Actions_File_Name);
end;
function Get_Shift_Reduce_File_Name return String is
begin
return Value_of(Shift_Reduce_File_Name);
end;
function Get_Goto_File_Name return String is
begin
return Value_of(Goto_File_Name);
end;
function Get_Tokens_File_Name return String is
begin
return Value_of(Tokens_File_Name);
end;
function Get_C_Lex_File_Name return String is
begin
return Value_of(C_Lex_File_Name);
end;
function Get_Include_File_Name return String is
begin
return Value_of(Include_File_Name);
end;
procedure Set_File_Names(Input_File, Extension: in String) is
Base: STR(Max_Name_Length);
begin
if Input_File'Length < 3 or else
(Input_File(Input_File'Last) /= 'y' and then
Input_File(Input_File'Last) /= 'Y') or else
Input_File(Input_File'Last - 1) /= '.'
then
raise Illegal_File_Name;
end if;
Assign(Input_File(Input_File'First..Input_File'Last-2), To => Base);
Assign(Input_File, To => Source_File_Name);
Assign(Base, To => Out_File_Name);
Append(Extension, To => Out_File_Name);
Assign(Base, To => Verbose_File_Name);
Append(".verbose", To => Verbose_File_Name);
Assign(Base, To => Tokens_File_Name);
Append("_tokens" & Extension, To => Tokens_File_Name);
Assign("yyparse.template", To => Template_File_Name);
Assign(Base, To => Actions_File_Name);
Append(".accs", To => Actions_File_Name);
Assign(Base, To => Shift_Reduce_File_Name);
Append("_shift_reduce" & Extension, To => Shift_Reduce_File_Name);
Assign(Base, To => Goto_File_Name);
Append("_goto" & Extension, To => Goto_File_Name);
Assign(Base, To => C_Lex_File_Name);
Append("_c_lex" & Extension, To => C_Lex_File_Name);
Assign(Base, To => Include_File_Name);
Append(".h", To => Include_File_Name);
end Set_File_Names;
end File_Names;
-- 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 : goto_file.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:29:33
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxgoto_file.ada
-- $Header: goto_file.a,v 0.1 86/04/01 15:04:27 ada Exp $
-- $Log: goto_file.a,v $
-- Revision 0.1 86/04/01 15:04:27 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:36:31 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.
--
package Goto_File is
procedure Open_Write;
procedure Close_Write;
procedure Write(S: in String);
procedure Write_Line(S: in String);
procedure Write(C: in Character);
end Goto_File;
with Text_IO, Rule_Table, Symbol_Table, File_Names;
use Text_IO, Rule_Table, Symbol_Table, File_Names;
package body Goto_File is
SCCS_ID : constant String := "@(#) goto_file.ada, Version 1.2";
Rcs_ID : constant String := "$Header: goto_file.a,v 0.1 86/04/01 15:04:27 ada Exp $";
The_File : File_Type;
procedure Open_Write is
begin
Create(The_File, Out_File, Get_Goto_File_Name);
Write_Line("package " & Goto_Tables_Unit_Name & " is");
Write_Line("");
Write_Line(" type Small_Integer is range -32_000 .. 32_000;");
Write_Line("");
Write_Line(" type Goto_Entry is record");
Write_Line(" Nonterm : Small_Integer;");
Write_Line(" Newstate : Small_Integer;");
Write_Line(" end record;");
Write_Line("");
Write_Line(" --pragma suppress(index_check);");
Write_Line("");
Write_Line(" subtype Row is Integer range -1 .. Integer'Last;");
Write_Line("");
Write_Line(" type Goto_Parse_Table is array (Row range <>) of " &
"Goto_Entry;");
Write_Line("");
Write_Line(" Goto_Matrix : constant Goto_Parse_Table :=");
Write_Line(" ((-1,-1) -- Dummy Entry.");
end Open_Write;
procedure Close_Write is
begin
Write_Line("");
Write_Line("subtype Rule is Natural;");
Write_Line("subtype Nonterminal is Integer;");
Write_Line("");
-- Write the rule length array --
Write( " Rule_Length : array (Rule range " & Rule'Image(First_Rule) &
" .. " & Rule'Image(Last_Rule) & ") of Natural := (");
for R in First_Rule..Last_Rule loop
Write( Natural'Image(Length_of(R)));
if R = Last_Rule then
Write_Line( ");");
elsif R mod 8 = 0 then
Write_Line( ",");
else
Write( ',');
end if;
end loop;
-- Write the lefth hand side array
Write(" Get_LHS_Rule: array (Rule range " &
Rule'Image(First_Rule) & " .. " &
Rule'Image(Last_Rule) & ") of Nonterminal := (");
for R in First_Rule..Last_Rule loop
if R = Last_Rule then
Write_Line( Grammar_Symbol'Image(Get_LHS(R)) & ");");
elsif R mod 8 = 0 then
Write_Line( Grammar_Symbol'Image(Get_LHS(R)) & ',');
else
Write(Grammar_Symbol'Image(Get_LHS(R)) & ',');
end if;
end loop;
Write_Line("end " & Goto_Tables_Unit_Name & ";");
Close(The_File);
end Close_Write;
procedure Write(S: in String) is
begin
Put(The_File, S);
end Write;
procedure Write_Line(S: in String) is
begin
Put_Line(The_File, S);
end Write_Line;
procedure Write(C: in Character) is
begin
Put(The_File, C);
end Write;
end Goto_File;
-- 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 : lalr_symbol_info.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:29:48
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxlalr_symbol_info.ada
-- $Header: lalr_symbol_info.a,v 0.1 86/04/01 15:04:35 ada Exp $
-- $Log: lalr_symbol_info.a,v $
-- Revision 0.1 86/04/01 15:04:35 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:36:38 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.
--
-- --
-- Authors : David Taback , Deepak Tolani --
-- Copyright : 1987, University of California Irvine --
-- --
-- If you --
-- modify the source code or if you have any suggestions or questions --
-- regarding ayacc, we would like to hear from you. Our mailing --
-- addresses are : --
-- taback@icsc.uci.edu --
-- tolani@icsc.uci.edu --
-- --
with LR0_Machine, Ragged, Rule_Table, Symbol_Table, Symbol_Info, Set_Pack,
Stack_Pack;
use LR0_Machine, Rule_Table, Symbol_Table, Symbol_Info;
with Text_IO; use Text_IO;
package LALR_Symbol_Info is
procedure Make_LALR_Sets;
procedure Get_LA(State_ID : Parse_State;
Item_ID : Item;
Look_Aheads : in out Grammar_Symbol_Set);
end LALR_Symbol_Info;
-- 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 : lalr_symbol_info_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:30:08
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxlalr_symbol_info_body.ada
-- $Header: lalr_symbol_info_body.a,v 0.1 86/04/01 15:04:40 ada Exp $
-- $Log: lalr_symbol_info_body.a,v $
-- Revision 0.1 86/04/01 15:04:40 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:36:47 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.
--
package body LALR_Symbol_Info is
SCCS_ID : constant String := "@(#) lalr_symbol_info_body.adadisk21~/rschm/hasee/sccs/ayacc, Version 1.2";
package Relation is
procedure Make_Reads_Relation;
procedure Make_Includes_Relation;
procedure Reads (LHS : Transition; RHS : in out Transition_Set);
procedure Includes(LHS : Transition; RHS : in out Transition_Set);
procedure Free_Includes;
end Relation;
package body Relation is
SCCS_ID : constant String := "@(#) lalr_symbol_info_body.adadisk21~/rschm/hasee/sccs/ayacc, Version 1.2";
package Includes_Relation is
new Ragged(Parse_State, Grammar_Symbol, Transition_Set,
Transition_Set_Pack.Make_Null);
procedure Make_Reads_Relation is
begin
-- Don't need to do anything. Get READS from the LR0 machine
null;
end Make_Reads_Relation;
-- Implements Algorithm D1 in Park's paper
-- "A New Analysis of LALR Formalisms" Park et al.
-- ACM Transactions on Programming Languages and Systems,
-- Vol 7,January 85.
use Includes_Relation, Item_Set_Pack,
Parse_State_Set_Pack, Transition_Set_Pack;
procedure Make_Includes_Relation is
Preds : Parse_State_Set;
Pred_Loop : Parse_State_Iterator;
Temp : Transition;
A , B : Grammar_Symbol;
R : Parse_State;
I : Item;
Items : Item_Set;
Item_Index : Item_Iterator;
begin
Make_Array(First_Parse_State,Last_Parse_State);
for Q in First_Parse_State .. Last_Parse_State loop
-- Loop over all items [B ->B1 . A B2] in state Q
-- Where A is a nonterminal and the string B2 is nullable.
Get_Kernel(Q, Items);
Closure(Items);
Initialize(Item_Index, Items);
while More(Item_Index) loop
Next(Item_Index,I);
-- Is the item of the form [B ->B1 . A B2] ?
if I.Dot_Position = Length_of(I.Rule_ID) then
goto Continue; -- Nothing to the right of dot
elsif I.Dot_Position + 1 < Get_Null_Pos(I.Rule_ID) then
goto Continue; -- B2 is not nullable
end if;
A := Get_RHS(I.Rule_ID, I.Dot_Position + 1);
B := Get_LHS(I.Rule_ID);
if Is_Terminal(A) then
goto Continue; -- A is not a nonterminal
end if;
-- for all states R in PRED(Q,B1) (Q,A) INCLUDES (R,B)
Make_Null(Preds);
Get_Pred_Set(Q,I,Preds);
Initialize(Pred_Loop, Preds);
while More(Pred_Loop) loop
Next(Pred_Loop, R);
Temp.State_ID := R;
Temp.Symbol := B;
Insert(Temp, Into => Includes_Relation.Lval(Q,A).Value);
end loop;
<<Continue>> null;
end loop;
end loop;
-- Free
Make_Null(Preds);
Make_Null(Items);
end Make_Includes_Relation;
procedure Free_Includes is
begin
Includes_Relation.Free_Array;
end Free_Includes;
use Grammar_Symbol_Set_Pack, Transition_Set_Pack;
procedure Reads (LHS : Transition; RHS : in out Transition_Set) is
Temp : Transition;
Gotos : Grammar_Symbol_Set;
Index : Grammar_Symbol_Iterator;
begin
Make_Null(RHS);
Temp.State_ID := Get_Goto(LHS.State_ID, LHS.Symbol);
Get_Transition_Symbols(Temp.State_ID, Nonterminals, Gotos);
Initialize(Index, Gotos);
while More(Index) loop
Next(Index, Temp.Symbol);
if Is_Nullable(Temp.Symbol) then
Insert(Temp, Into => RHS);
end if;
end loop;
-- Free
Make_Null(Gotos);
end Reads;
use Includes_Relation, Transition_Set_Pack;
procedure Includes (LHS : Transition; RHS : in out Transition_Set) is
begin
-- Free
Make_Null(RHS);
-- Could use fassign but dangerous
Assign(RHS, Includes_Relation.Lval(LHS.State_ID,LHS.Symbol).Value);
end Includes;
end Relation;
--------------------------------------------------------------------------
use Relation;
package LALR_Sets_Pack is
procedure Make_Dr_Sets;
procedure Make_Read_Sets;
procedure Make_Follow_Sets;
procedure Follow(
Trans : Transition;
Follow_Set: in out Grammar_Symbol_Set);
procedure Union_Follow_Sets(
Trans : Transition;
Follow_Set : in out Grammar_Symbol_Set);
end LALR_Sets_Pack;
package body LALR_Sets_Pack is
SCCS_ID : constant String := "@(#) lalr_symbol_info_body.adadisk21~/rschm/hasee/sccs/ayacc, Version 1.2";
-- The DR, Read, and Follow sets are all stored in the same data
-- structure in package lalr_sets.
type Relation_Type is (Use_Reads, Use_Includes);
package LALR_Sets is new
Ragged(Parse_State, Grammar_Symbol,
Grammar_Symbol_Set, Grammar_Symbol_Set_Pack.Make_Null);
use LALR_Sets, Grammar_Symbol_Set_Pack, Transition_Set_Pack;
procedure Make_Dr_Sets is
Trans : Transition;
-- gotos : transition_set;
Goto_Index : Nt_Transition_Iterator;
Term_Sym : Grammar_Symbol;
Terms : Grammar_Symbol_Set;
Term_Index : Grammar_Symbol_Iterator;
begin
-- Make storage to hold the DR sets.
LALR_Sets.Make_Array(First_Parse_State, Last_Parse_State);
-- DR(P,Symbol) = { x is a terminal|P -Symbol-> Next_State -x->}
for P in First_Parse_State..Last_Parse_State loop
-- Get all transitions (Symbol,Next_State) out of state P
-- get_transitions(P, nonterminals, gotos);
Initialize(Goto_Index, P);
while More(Goto_Index) loop
Next(Goto_Index, Trans);
Get_Transition_Symbols(Trans.State_ID, Terminals, Terms);
Initialize(Term_Index, Terms);
while More(Term_Index) loop
Next(Term_Index, Term_Sym);
Insert(Term_Sym,
Into => LALR_Sets.Lval(P,Trans.Symbol).Value);
end loop;
end loop;
end loop;
-- make_null(gotos);
Make_Null(Terms);
end Make_Dr_Sets;
procedure Initialize_N(X: in out Integer) is
begin
X := 0;
end Initialize_N;
procedure Digraph(R : Relation_Type) is
package N is new Ragged(Parse_State, Grammar_Symbol, Integer,
Initialize_N);
package Transition_Stack is new Stack_Pack(Transition);
use Transition_Stack, Transition_Set_Pack;
Trans_Stack : Stack;
Symbol : Grammar_Symbol;
Gotos : Grammar_Symbol_Set;
Goto_Index : Grammar_Symbol_Iterator;
Trans : Transition;
procedure Traverse(X: Transition) is
Infinity : constant Integer := Integer'Last;
Depth : Integer;
Minimum : Integer;
Y, Top : Transition;
RHS_Set : Transition_Iterator;
Related : Transition_Set;
begin
Push(Trans_Stack,X);
Depth := Depth_of_Stack(Trans_Stack);
N.Lval(X.State_ID,X.Symbol).Value := Depth;
-- Should take a procedure parameter instead of a key
if R = Use_Reads then
Reads(X, Related);
else
Includes(X, Related);
end if;
Initialize(RHS_Set, Related);
while More(RHS_Set) loop
Next(RHS_Set, Y);
if N.Lval(Y.State_ID, Y.Symbol).Value = 0 then
Traverse(Y);
end if;
Minimum := N.Rval(Y.State_ID, Y.Symbol).Value;
if Minimum < N.Rval(X.State_ID, X.Symbol).Value then
N.Lval(X.State_ID, X.Symbol).Value := Minimum;
end if;
Insert(LALR_Sets.Lval(Y.State_ID,Y.Symbol).Value,
Into => LALR_Sets.Lval(X.State_ID,X.Symbol).Value);
end loop;
if N.Rval(X.State_ID, X.Symbol).Value = Depth then
loop
Top := Top_Value(Trans_Stack);
N.Lval(Top.State_ID,Top.Symbol).Value:= Infinity;
Assign(LALR_Sets.Lval(Top.State_ID, Top.Symbol).Value,
LALR_Sets.Rval(X.State_ID, X.Symbol).Value);
Pop(Trans_Stack, Top);
exit when Top = X;
end loop;
end if;
-- Free
Make_Null(Related);
exception
when Value_Range_Error =>
Put_Line("Ayacc: Value Range Error in Traverse");
raise;
when Stack_Underflow =>
Put_Line("Ayacc: Stack Underflow in Traverse");
raise;
when others =>
Put_Line("Ayacc: Unexpected Error in Traverse");
raise;
end Traverse;
begin -- digraph
Make_Stack(Trans_Stack);
N.Make_Array(First_Parse_State, Last_Parse_State);
-- Call traverse(X) for all unexamined nonterminal transitions X
for State in First_Parse_State .. Last_Parse_State loop
Get_Transition_Symbols(State, Nonterminals, Gotos);
Initialize(Goto_Index, Gotos);
while More(Goto_Index) loop
Next(Goto_Index, Symbol);
if N.Lval(State, Symbol).Value = 0 then
Trans.State_ID := State;
Trans.Symbol := Symbol;
Traverse(Trans);
end if;
end loop;
end loop;
Free_Stack(Trans_Stack);
N.Free_Array;
-- Free
Make_Null(Gotos);
exception
when Value_Range_Error =>
Put_Line("Ayacc: Value Range Error in Digraph");
raise;
when Stack_Underflow =>
Put_Line("Ayacc: Stack Underflow in Digraph");
raise;
when others =>
Put_Line("Ayacc: Unexpected Error in Digraph");
raise;
end Digraph;
procedure Make_Read_Sets is
begin
Digraph(Use_Reads);
end Make_Read_Sets;
procedure Make_Follow_Sets is
begin
Digraph(Use_Includes);
Free_Includes;
end Make_Follow_Sets;
procedure Follow(
Trans : Transition;
Follow_Set : in out Grammar_Symbol_Set) is
begin
Make_Null(Follow_Set);
Assign(Follow_Set,
LALR_Sets.Lval(Trans.State_ID,Trans.Symbol).Value);
-- used to rval
end Follow;
procedure Union_Follow_Sets(
Trans : Transition;
Follow_Set: in out Grammar_Symbol_Set) is
begin
Insert(LALR_Sets.Rval(Trans.State_ID,Trans.Symbol).Value,
Into => Follow_Set);
end Union_Follow_Sets;
end LALR_Sets_Pack;
--------------------------------------------------------------------------
use Relation, LALR_Sets_Pack;
procedure Make_LALR_Sets is
begin
Make_Dr_Sets;
Make_Reads_Relation;
Make_Read_Sets;
Make_Includes_Relation;
Make_Follow_Sets;
end Make_LALR_Sets;
--------------------------------------------------------------------------
use Grammar_Symbol_Set_Pack, Parse_State_Set_Pack;
procedure Get_LA(State_ID : Parse_State;
Item_ID : Item;
Look_Aheads : in out Grammar_Symbol_Set) is
Predecessors : Parse_State_Set;
Pred_Loop : Parse_State_Iterator;
Temp : Transition;
begin
Make_Null(Look_Aheads);
Temp.Symbol := Get_LHS(Item_ID.Rule_ID);
Make_Null(Predecessors);
Get_Pred_Set(State_ID, Item_ID ,Predecessors);
Initialize(Pred_Loop, Predecessors);
while More(Pred_Loop) loop
Next(Pred_Loop, Temp.State_ID);
Union_Follow_Sets(Temp, Look_Aheads);
end loop;
-- Free
Make_Null(Predecessors);
end Get_LA;
end LALR_Symbol_Info;
-- 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 : lexical_analyzer.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:30:26
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxlexical_analyzer.ada
-- $Header: lexical_analyzer.a,v 0.1 86/04/01 15:05:14 ada Exp $
-- $Log: lexical_analyzer.a,v $
-- Revision 0.1 86/04/01 15:05:14 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:36:57 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 Source_File;
package Lexical_Analyzer is
function Get_Lexeme_Text return String; -- Scanned text.
type Ayacc_Token is
(Token, Start,
Left, Right, Nonassoc, Prec,
With_Clause, Use_Clause,
Identifier, Character_Literal,
Comma, Colon, Semicolon, Vertical_Bar, Left_Brace,
Mark, Eof_Token);
function Get_Token return Ayacc_Token;
function Line_Number return Natural; -- Current line of source file
procedure Handle_Action(Rule, Rule_Length : Integer);
procedure Print_Context_Lines renames Source_File.Print_Context_Lines;
procedure Dump_Declarations;
Illegal_Token : exception;
end Lexical_Analyzer;
-- 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 : lexical_analyzer_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:30:42
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxlexical_analyzer_body.ada
-- $Header: lexical_analyzer_body.a,v 0.1 86/04/01 15:05:27 ada Exp $
-- $Log: lexical_analyzer_body.a,v $
-- Revision 0.1 86/04/01 15:05:27 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:37:05 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 Actions_File, Source_File, STR_Pack, Tokens_File, Text_IO;
use Actions_File, Source_File, STR_Pack, Tokens_File, Text_IO;
package body Lexical_Analyzer is
SCCS_ID : constant String := "@(#) lexical_analyzer_body.adadisk21~/rschm/hasee/sccs/ayacc, Version 1.2";
Rcs_ID : constant String := "$Header: lexical_analyzer_body.a,v 0.1 86/04/01 15:05:27 ada Exp $";
Max_Lexeme_Length : constant := 80;
Current_Line_Number: Natural := 1;
Lexeme_Text : STR(Max_Lexeme_Length);
function Get_Lexeme_Text return String is
begin
return Value_of(Lexeme_Text);
end Get_Lexeme_Text;
function Line_Number return Natural is
begin
return Source_Line_Number;
end Line_Number;
procedure Skip_Comment is
Ch: Character;
begin
loop
Get_Char(Ch);
if Ch = Eof then
Unget_Char(Ch);
exit;
elsif Ch = Eoln then
Current_Line_Number := Current_Line_Number + 1;
exit;
end if;
end loop;
end Skip_Comment;
function Get_Token return Ayacc_Token is
Ch: Character;
begin
loop
Assign("", To => Lexeme_Text);
loop
Get_Char(Ch);
if Ch = Eoln then
Current_Line_Number := Current_Line_Number + 1;
end if;
exit when Ch /= ' ' and then
Ch /= Eoln and then
Ch /= Ascii.Ht;
end loop;
case Ch is
when '-' =>
Get_Char(Ch);
if Ch = '-' then
Skip_Comment;
else
raise Illegal_Token;
end if;
when ':' =>
Append(Ch, To => Lexeme_Text);
return Colon;
when ';' =>
Append(Ch, To => Lexeme_Text);
return Semicolon;
when ',' =>
Append(Ch, To => Lexeme_Text);
return Comma;
when '%' =>
Append(Ch, To => Lexeme_Text);
if Peek_Next_Char = '%' then
Get_Char(Ch);
Append(Ch, To => Lexeme_Text);
return Mark;
else
loop
Get_Char(Ch);
if Ch not in 'A'..'Z' and then
Ch not in 'a'..'z' then
Unget_Char(Ch);
exit;
end if;
Append(Ch, To => Lexeme_Text);
end loop;
Upper_Case(Lexeme_Text);
if Value_of(Lexeme_Text) = "%TOKEN" then
return Token;
elsif Value_of(Lexeme_Text) = "%START" then
return Start;
elsif Value_of(Lexeme_Text) = "%LEFT" then
return Left;
elsif Value_of(Lexeme_Text) = "%RIGHT" then
return Right;
elsif Value_of(Lexeme_Text) = "%NONASSOC" then
return Nonassoc;
elsif Value_of(Lexeme_Text) = "%PREC" then
return Prec;
elsif Value_of (Lexeme_Text) = "%WITH" then
return With_Clause;
elsif Value_of (Lexeme_Text) = "%USE" then
return Use_Clause;
else
raise Illegal_Token;
end if;
end if;
when '|' =>
Append(Ch, To => Lexeme_Text);
return Vertical_Bar;
when '{' =>
Append(Ch, To => Lexeme_Text);
return Left_Brace;
when Eof =>
return Eof_Token;
when ''' =>
Append(Ch, To => Lexeme_Text);
Get_Char(Ch);
if Ch /= Eof and Ch /= Eoln then
Append(Ch, To => Lexeme_Text);
Get_Char(Ch);
if Ch /= ''' then
raise Illegal_Token;
else
Append(Ch, To => Lexeme_Text);
end if;
return Character_Literal;
end if;
when 'A'..'Z' | 'a'..'z' | '.' | '_' =>
Append(Ch, To => Lexeme_Text);
loop
Get_Char(Ch);
if Ch in 'a'..'z' or else
Ch in 'A'..'Z' or else
Ch in '0'..'9' or else
Ch = '.' or else
Ch = '_'
then
Append(Ch, To => Lexeme_Text);
else
Unget_Char(Ch);
exit;
end if;
end loop;
Upper_Case(Lexeme_Text);
return Identifier;
when others =>
raise Illegal_Token;
end case;
end loop;
end Get_Token;
procedure Handle_Action(Rule, Rule_Length : Integer) is
Char : Character;
Base : Integer;
begin
Actions_File.Writeln;
Actions_File.Write("when " & Integer'Image(Rule) & " =>");
Actions_File.Writeln;
Actions_File.Write("--#line " & Integer'Image(Current_Line_Number));
Actions_File.Writeln;
loop
Get_Char(Char);
if Char = '-' and then Peek_Next_Char = '-' then
loop
Actions_File.Write(Char);
Get_Char(Char);
exit when Char = Eoln;
end loop;
end if;
case Char is
when '"' =>
Actions_File.Write(Char);
loop
Get_Char(Char);
Actions_File.Write(Char);
exit when Char = '"';
end loop;
-- handle special case '"' where there is no matching ".
when ''' =>
Actions_File.Write(Char);
if Peek_Next_Char= '"' then
Get_Char(Char);
if Peek_Next_Char = ''' then
Actions_File.Write(Char); -- '"'
Get_Char(Char); -- '''
Actions_File.Write(Char);
else
UnGet_Char(Char); -- '"'
end if;
end if;
when '$' =>
Actions_File.Writeln;
Get_Char(Char);
if Char = '$' then
Actions_File.Write("yyval");
elsif Char in '0'..'9' then
Base := Character'Pos(Char) - Character'Pos('0');
while Peek_Next_Char in '0'..'9' loop
Get_Char(Char);
Base := Base * 10 +
Character'Pos(Char) - Character'Pos('0');
end loop;
if Base > Rule_Length then
Put_Line("Ayacc: Illegal use of $"&Integer'Image(Base));
raise Illegal_Token;
end if;
Base := Base - Rule_Length;
if Base = 0 then
Actions_File.Write("yy.value_stack(yy.tos)");
else
Actions_File.Write("yy.value_stack(yy.tos" &
Integer'Image(Base) & ")");
end if;
else
Put_Line("Ayacc: Illegal symbol following $");
raise Illegal_Token;
end if;
when Eoln =>
Actions_File.Writeln;
Current_Line_Number := Current_Line_Number + 1;
when '}' =>
exit;
when others =>
Actions_File.Write(Char);
end case;
end loop;
Actions_File.Writeln;
end Handle_Action;
procedure Dump_Declarations is
Ch : Character;
Text : STR(Source_File.Maximum_Line_Length);
begin
Assign("", To => Text);
loop
Get_Char(Ch);
exit when Ch = '}' ;
case Ch is
when '-' => Append(Ch, To => Text);
if Peek_Next_Char = '-' then
loop
Get_Char(Ch);
Append(Ch, To => Text);
exit when Peek_Next_Char = Eoln or
Peek_Next_Char = Eof;
end loop;
end if;
when '"' => Append(Ch, To => Text);
loop
Get_Char(Ch);
if Ch = Eoln or Ch = Eof then
raise Illegal_Token;
end if;
Append(Ch, To => Text);
exit when Ch = '"';
end loop;
when Eoln => Tokens_File.Writeln(Value_of(Text));
Assign("", To => Text);
Current_Line_Number := Current_Line_Number + 1;
when Eof => exit;
when others => Append(Ch, To => Text);
end case;
end loop;
Tokens_File.Writeln(Value_of(Text));
end Dump_Declarations;
end Lexical_Analyzer;
with Unchecked_Deallocation;
package body Lists is
procedure Free is
new Unchecked_Deallocation (Element_Type, Element_Pointer);
--------------------------------------------------------------------------
procedure Attach (List1 : in out List;
List2 : in List) is
Endoflist1 : Element_Pointer;
--| Attach List2 to List1.
--| If List1 is null return List2
--| If List1 equals List2 then raise CircularList
--| Otherwise get the pointer to the last element of List1 and change
--| its Next field to be List2.
begin
if List1.Head = null then
List1 := List2;
elsif List1 = List2 then
raise Circularlist;
else
Endoflist1 := List1.Tail;
Endoflist1.Next := List2.Head;
List1.Tail := List2.Tail;
end if;
end Attach;
--------------------------------------------------------------------------
procedure Attach (L : in out List;
Element : in Itemtype) is
Old_Tail, New_Element : Element_Pointer;
--| Create a list containing Element and attach it to the end of L
begin
New_Element := new Element_Type'(Item => Element, Next => null);
if L.Head = null then
L.Head := New_Element;
L.Tail := New_Element;
else
Old_Tail := L.Tail;
Old_Tail.Next := New_Element;
L.Tail := New_Element;
end if;
end Attach;
--------------------------------------------------------------------------
function Attach (Element1 : in Itemtype;
Element2 : in Itemtype) return List is
Newlist : List;
--| Create a new list containing the information in Element1 and
--| attach Element2 to that list.
begin
Newlist.Head := new Element_Type'(Item => Element1, Next => null);
Newlist.Tail := NewList.Head;
Attach (Newlist, Element2);
return Newlist;
end Attach;
--------------------------------------------------------------------------
procedure Attach (Element : in Itemtype;
L : in out List) is
--| Create a new cell whose information is Element and whose Next
--| field is the list L. This prepends Element to the List L.
Old_Head, New_Head : Element_Pointer;
begin
if L.Head = null then
L.Head := new Element_Type'(Item => Element, Next => null);
L.Tail := L.Head;
else
Old_Head := L.Head;
New_Head := new Element_Type'(Item => Element, Next => Old_Head);
L.Head := New_Head;
end if;
end Attach;
--------------------------------------------------------------------------
function Attach (List1 : in List;
List2 : in List) return List is
--| Attach List2 to List1.
--| If List1 is null return List2
--| If List1 equals List2 then raise CircularList
--| Otherwise get the pointer to the last element of List1 and change
--| its Next field to be List2.
End_Of_List1 : Element_Pointer;
New_List : List;
begin
if List1.Head = null then
return List2;
elsif List1 = List2 then
raise Circularlist;
else
End_Of_List1 := List1.Tail;
End_Of_List1.Next := List2.Head;
New_List.Head := List1.Head;
New_List.Tail := List2.Tail;
return New_List;
end if;
end Attach;
-------------------------------------------------------------------------
function Attach (L : in List;
Element : in Itemtype) return List is
New_Element : Element_Pointer;
New_List : List;
End_Of_List : Element_Pointer;
--| Create a list called New_List and attach it to the end of L.
--| If L is null return New_List
--| Otherwise get the last element in L and make its Next field
--| New_List.
begin
New_Element := new Element_Type'(Item => Element, Next => null);
if L.Head = null then
New_List := (Head => New_Element, Tail => New_Element);
else
End_Of_List := L.Tail;
End_Of_List.Next := New_Element;
New_List := (Head => L.Head, Tail => New_Element);
end if;
return New_List;
end Attach;
--------------------------------------------------------------------------
function Attach (Element : in Itemtype;
L : in List) return List is
New_Element : Element_Pointer;
begin
if L.Head = null then
New_Element := new Element_Type'(Item => Element, Next => null);
return (Head => New_Element, Tail => New_Element);
else
New_Element := new Element_Type'(Item => Element, Next => L.Head);
return (Head => New_Element, Tail => L.Tail);
end if;
end Attach;
--------------------------------------------------------------------------
function Copy (L : in List) return List is
--| If L is null return null
--| Otherwise recursively copy the list by first copying the information
--| at the head of the list and then making the Next field point to
--| a copy of the tail of the list.
Current_Element : Element_Pointer := L.Head;
New_List : List := (Head => null, Tail => null);
begin
while Current_Element /= null loop
Attach (New_List, Current_Element.Item);
Current_Element := Current_Element.Next;
end loop;
return New_List;
end Copy;
--------------------------------------------------------------------------
--generic
-- with function Copy (I : in Itemtype) return Itemtype;
function Copydeep (L : in List) return List is
--| If L is null then return null.
--| Otherwise copy the first element of the list into the head of the
--| new list and copy the tail of the list recursively using CopyDeep.
Current_Element : Element_Pointer := L.Head;
New_List : List := (Head => null, Tail => null);
begin
while Current_Element /= null loop
Attach (New_List, Copy (Current_Element.Item));
Current_Element := Current_Element.next;
end loop;
return New_List;
end Copydeep;
--------------------------------------------------------------------------
function Create return List is
--| Return the empty list.
begin
return (Head => null, Tail => null);
end Create;
--------------------------------------------------------------------------
procedure Deletehead (L : in out List) is
New_Head : Element_Pointer;
--| Remove the element of the head of the list and return it to the heap.
--| If L is null EmptyList.
--| Otherwise save the Next field of the first element, remove the first
--| element and then assign to L the Next field of the first element.
begin
if L.Head = null then
raise Emptylist;
else
New_Head := L.Head.Next;
Free (L.Head);
L.Head := New_Head;
end if;
end Deletehead;
--------------------------------------------------------------------------
procedure Deleteitem (L : in out List;
Element : in Itemtype) is
--| Remove the first element in the list with the value Element.
--| If the first element of the list is equal to element then
--| remove it. Otherwise, recurse on the tail of the list.
Current_Element, Previous_Element : Element_Pointer;
begin
if L.Head = null then
raise Itemnotpresent;
elsif Equal (L.Head.Item, Element) then
Deletehead (L);
else
Current_Element := L.Head.Next;
Previous_Element := L.Head;
while Current_Element /= null and then
not Equal (Current_Element.Item, Element) loop
Previous_Element := Current_Element;
Current_Element := Current_Element.Next;
end loop;
if Current_Element = null then
raise Itemnotpresent;
else
if Current_Element = L.Tail then
L.Tail := Previous_Element;
end if;
Previous_Element.Next := Current_Element.Next;
Free (Current_Element);
end if;
end if;
end Deleteitem;
--------------------------------------------------------------------------
procedure Deleteitems (L : in out List;
Element : in Itemtype) is
Delete_List_Is_Empty : Boolean := True;
New_List_Is_Empty : Boolean := True;
Old_Tail : Element_Pointer;
Current_Element : Element_Pointer := L.Head;
New_List, Delete_List : List;
procedure Append (Element : in out Element_Pointer;
To_List : in out List) is
begin
if To_List.Head = null then
To_List.Head := Element;
To_List.Tail := Element;
else
Old_Tail := To_List.Tail;
To_List.Tail := Element;
Old_Tail.Next := To_List.Tail;
end if;
end Append;
begin
while Current_Element /= null loop
if Equal (Current_Element.Item, Element) then
Append (Element => Current_Element,
To_List => Delete_List);
Delete_List_Is_Empty := False;
else
Append (Element => Current_Element,
To_List => New_List);
New_List_Is_Empty := False;
end if;
Current_Element := Current_Element.Next;
end loop;
if Delete_List_Is_Empty then
raise Itemnotpresent;
else
Delete_List.Tail.Next := null;
Destroy (Delete_List);
end if;
if not New_List_Is_Empty then
New_List.Tail.Next := null;
end if;
L := New_List;
end Deleteitems;
--------------------------------------------------------------------------
procedure Destroy (L : in out List) is
Current_Element : Element_Pointer := L.Head;
Element_To_Delete : Element_Pointer;
--| Walk down the list removing all the elements and set the list to
--| the empty list.
begin
if L.Head /= null then
while Current_Element /= null loop
Element_To_Delete := Current_Element;
Current_Element := Current_Element.Next;
Free (Element_To_Delete);
end loop;
L := (Head => null, Tail => null);
end if;
end Destroy;
--------------------------------------------------------------------------
function Firstvalue (L : in List) return Itemtype is
--| Return the first value in the list.
begin
if L.Head = null then
raise Emptylist;
else
return L.Head.Item;
end if;
end Firstvalue;
--------------------------------------------------------------------------
function Isinlist (L : in List;
Element : in Itemtype) return Boolean is
Current_Element : Element_Pointer := L.Head;
--| Check if Element is in L. If it is return true otherwise return false.
begin
while Current_Element /= null and then
not Equal (Current_Element.Item, Element) loop
Current_Element := Current_Element.Next;
end loop;
return Current_Element /= null;
end Isinlist;
--------------------------------------------------------------------------
function Isempty (L : in List) return Boolean is
--| Is the list L empty.
begin
return L.Head = null;
end Isempty;
--------------------------------------------------------------------------
function Lastvalue (L : in List) return Itemtype is
--| Return the value of the last element of the list. Get the pointer
--| to the last element of L and then return its information.
begin
if L.Head = null then
raise Emptylist;
else
return L.Tail.Item;
end if;
end Lastvalue;
--------------------------------------------------------------------------
function Length (L : in List) return Integer is
--| Recursively compute the length of L. The length of a list is
--| 0 if it is null or 1 + the length of the tail.
Current_Element : Element_Pointer := L.Head;
List_Length : Natural := 0;
begin
while Current_Element /= null loop
List_Length := List_Length + 1;
Current_Element := Current_Element.Next;
end loop;
return List_Length;
end Length;
--------------------------------------------------------------------------
function Makelistiter (L : in List) return Listiter is
--| Start an iteration operation on the list L. Do a type conversion
--| from List to ListIter.
begin
return Listiter (L);
end Makelistiter;
--------------------------------------------------------------------------
function More (L : in Listiter) return Boolean is
--| This is a test to see whether an iteration is complete.
begin
return L.Head /= null;
end More;
--------------------------------------------------------------------------
procedure Next (Place : in out Listiter;
Info : out Itemtype) is
--| This procedure gets the information at the current place in the List
--| and moves the ListIter to the next postion in the list.
--| If we are at the end of a list then exception NoMore is raised.
Next_Element : Element_Pointer := Place.Head;
begin
if Next_Element = null then
raise Nomore;
else
Info := Next_Element.Item;
Place.Head := Next_Element.Next;
end if;
end Next;
--------------------------------------------------------------------------
procedure Replacehead (L : in out List;
Info : in Itemtype) is
--| This procedure replaces the information at the head of a list
--| with the given information. If the list is empty the exception
--| EmptyList is raised.
begin
if L.Head = null then
raise Emptylist;
else
L.Head.Item := Info;
end if;
end Replacehead;
--------------------------------------------------------------------------
procedure Replacetail (L : in out List;
Newtail : in List) is
List_Head_Item : Itemtype;
--| This destroys the tail of a list and replaces the tail with
--| NewTail. If L is empty EmptyList is raised.
begin
if L.Head = null then
raise Emptylist;
else
List_Head_Item := L.Head.Item;
Destroy (L);
L := Attach (List_Head_Item, Newtail);
end if;
end Replacetail;
--------------------------------------------------------------------------
function Tail (L : in List) return List is
--| This returns the list which is the tail of L. If L is null Empty
--| List is raised.
begin
if L.Head = null then
raise Emptylist;
else
return (Head => L.Head.Next, Tail => L.Tail);
end if;
end Tail;
--------------------------------------------------------------------------
function Equal (List1 : in List;
List2 : in List) return Boolean is
Placeinlist1 : Element_Pointer := List1.Head;
Placeinlist2 : Element_Pointer := List2.Head;
Contents1 : Itemtype;
Contents2 : Itemtype;
--| This function tests to see if two lists are equal. Two lists
--| are equal if for all the elements of List1 the corresponding
--| element of List2 has the same value. Thus if the 1st elements
--| are equal and the second elements are equal and so up to n.
--| Thus a necessary condition for two lists to be equal is that
--| they have the same number of elements.
--| This function walks over the two list and checks that the
--| corresponding elements are equal. As soon as we reach
--| the end of a list (PlaceInList = null) we fall out of the loop.
--| If both PlaceInList1 and PlaceInList2 are null after exiting the loop
--| then the lists are equal. If they both are not null the lists aren't
--| equal. Note that equality on elements is based on a user supplied
--| function Equal which is used to test for item equality.
begin
while (Placeinlist1 /= null) and then (Placeinlist2 /= null) loop
if not Equal (Placeinlist1.Item, Placeinlist2.Item) then
return False;
end if;
Placeinlist1 := Placeinlist1.Next;
Placeinlist2 := Placeinlist2.Next;
end loop;
return ((Placeinlist1 = null) and then (Placeinlist2 = null));
end Equal;
end Lists;
generic
type Itemtype is private; --| This is the data being manipulated.
with function Equal (X, Y : in Itemtype) return Boolean is "=";
--| This allows the user to define
--| equality on ItemType. For instance
--| if ItemType is an abstract type
--| then equality is defined in terms of
--| the abstract type. If this function
--| is not provided equality defaults to
--| =.
package Lists is
--| This package provides singly linked lists with elements of type
--| ItemType, where ItemType is specified by a generic parameter.
--| Overview
--| When this package is instantiated, it provides a linked list type for
--| lists of objects of type ItemType, which can be any desired type. A
--| complete set of operations for manipulation, and releasing
--| those lists is also provided. For instance, to make lists of strings,
--| all that is necessary is:
--|
--| type StringType is string(1..10);
--|
--| package Str_List is new Lists(StringType); use Str_List;
--|
--| L:List;
--| S:StringType;
--|
--| Then to add a string S, to the list L, all that is necessary is
--|
--| L := Create;
--| Attach(S,L);
--|
--|
--| This package provides basic list operations.
--|
--| Attach append an object to an object, an object to a list,
--| or a list to an object, or a list to a list.
--| Copy copy a list using := on elements
--| CopyDeep copy a list by copying the elements using a copy
--| operation provided by the user
--| Create Creates an empty list
--| DeleteHead removes the head of a list
--| DeleteItem delete the first occurrence of an element from a list
--| DeleteItems delete all occurrences of an element from a list
--| Destroy remove a list
--| Equal are two lists equal
--| FirstValue get the information from the first element of a list
--| IsInList determines whether a given element is in a given list
--| IsEmpty returns true if the list is empty
--| LastValue return the last value of a list
--| Length Returns the length of a list
--| MakeListIter prepares for an iteration over a list
--| More are there any more items in the list
--| Next get the next item in a list
--| ReplaceHead replace the information at the head of the list
--| ReplaceTail replace the tail of a list with a new list
--| Tail get the tail of a list
--|
--| N/A: Effects, Requires, Modifies, and Raises.
--| Notes
--| Programmer Buddy Altus
--| Types
--| -----
type List is private;
type Listiter is private;
--| Exceptions
--| ----------
Circularlist : exception; --| Raised if an attemp is made to
--| create a circular list. This
--| results when a list is attempted
--| to be attached to itself.
Emptylist : exception; --| Raised if an attemp is made to
--| manipulate an empty list.
Itemnotpresent : exception; --| Raised if an attempt is made to
--| remove an element from a list in
--| which it does not exist.
Nomore : exception; --| Raised if an attemp is made to
--| get the next element from a list
--| after iteration is complete.
--| Operations
--| ----------
----------------------------------------------------------------------------
procedure Attach ( --| appends List2 to List1
List1 : in out List; --| The list being appended to.
List2 : in List --| The list being appended.
);
--| Raises
--| CircularList
--| Effects
--| Appends List1 to List2. This makes the next field of the last element
--| of List1 refer to List2. This can possibly change the value of List1
--| if List1 is an empty list. This causes sharing of lists. Thus if
--| user Destroys List1 then List2 will be a dangling reference.
--| This procedure raises CircularList if List1 equals List2. If it is
--| necessary to Attach a list to itself first make a copy of the list and
--| attach the copy.
--| Modifies
--| Changes the next field of the last element in List1 to be List2.
-------------------------------------------------------------------------------
function Attach ( --| Creates a new list containing the two
--| Elements.
Element1 : in Itemtype;
--| This will be first element in list.
Element2 : in Itemtype
--| This will be second element in list.
) return List;
--| Effects
--| This creates a list containing the two elements in the order
--| specified.
-------------------------------------------------------------------------------
procedure Attach ( --| List L is appended with Element.
L : in out List; --| List being appended to.
Element : in Itemtype
--| This will be last element in l ist.
);
--| Effects
--| Appends Element onto the end of the list L. If L is empty then this
--| may change the value of L.
--|
--| Modifies
--| This appends List L with Element by changing the next field in List.
--------------------------------------------------------------------------------
procedure Attach ( --| Makes Element first item in list L.
Element : in Itemtype;
--| This will be the first element in list.
L : in out List --| The List which Element is being
--| prepended to.
);
--| Effects
--| This prepends list L with Element.
--|
--| Modifies
--| This modifies the list L.
--------------------------------------------------------------------------
function Attach ( --| attaches two lists
List1 : in List; --| first list
List2 : in List --| second list
) return List;
--| Raises
--| CircularList
--| Effects
--| This returns a list which is List1 attached to List2. If it is desired
--| to make List1 be the new attached list the following ada code should be
--| used.
--|
--| List1 := Attach (List1, List2);
--| This procedure raises CircularList if List1 equals List2. If it is
--| necessary to Attach a list to itself first make a copy of the list and
--| attach the copy.
-------------------------------------------------------------------------
function Attach ( --| prepends an element onto a list
Element : in Itemtype; --| element being prepended to list
L : in List --| List which element is being added
--| to
) return List;
--| Effects
--| Returns a new list which is headed by Element and followed by L.
------------------------------------------------------------------------
function Attach ( --| Adds an element to the end of a list
L : in List;
--| The list which element is being added to.
Element : in Itemtype
--| The element being added to the end of
--| the list.
) return List;
--| Effects
--| Returns a new list which is L followed by Element.
--------------------------------------------------------------------------
function Copy ( --| returns a copy of list1
L : in List --| list being copied
) return List;
--| Effects
--| Returns a copy of L.
--------------------------------------------------------------------------
generic
with function Copy (I : in Itemtype) return Itemtype;
function Copydeep ( --| returns a copy of list using a user supplied
--| copy function. This is helpful if the type
--| of a list is an abstract data type.
L : in List --| List being copied.
) return List;
--| Effects
--| This produces a new list whose elements have been duplicated using
--| the Copy function provided by the user.
------------------------------------------------------------------------------
function Create --| Returns an empty List
return List;
------------------------------------------------------------------------------
procedure Deletehead ( --| Remove the head element from a list.
L : in out List --| The list whose head is being removed.
);
--| Raises
--| EmptyList
--|
--| Effects
--| This will return the space occupied by the first element in the list
--| to the heap. If sharing exists between lists this procedure
--| could leave a dangling reference. If L is empty EmptyList will be
--| raised.
------------------------------------------------------------------------------
procedure Deleteitem ( --| remove the first occurrence of Element
--| from L
L : in out List;
--| list element is being removed from
Element : in Itemtype --| element being removed
);
--| Raises
--| ItemNotPresent
--| Effects
--| Removes the first element of the list equal to Element. If there is
--| not an element equal to Element than ItemNotPresent is raised.
--| Modifies
--| This operation is destructive, it returns the storage occupied by
--| the elements being deleted.
------------------------------------------------------------------------------
procedure Deleteitems ( --| remove all occurrences of Element
--| from L.
L : in out List;
--| The List element is being removed from
Element : in Itemtype --| element being removed
);
--| Raises
--| ItemNotPresent
--|
--| Effects
--| This procedure walks down the list L and removes all elements of the
--| list equal to Element. If there are not any elements equal to Element
--| then raise ItemNotPresent.
--| Modifies
--| This operation is destructive the storage occupied by the items
--| removed is returned.
------------------------------------------------------------------------------
procedure Destroy ( --| removes the list
L : in out List --| the list being removed
);
--| Effects
--| This returns to the heap all the storage that a list occupies. Keep in
--| mind if there exists sharing between lists then this operation can leave
--| dangling references.
------------------------------------------------------------------------------
function Firstvalue ( --| returns the contents of the first record of the
--| list
L : in List --| the list whose first element is being
--| returned
) return Itemtype;
--| Raises
--| EmptyList
--|
--| Effects
--| This returns the Item in the first position in the list. If the list
--| is empty EmptyList is raised.
-------------------------------------------------------------------------------
function Isempty ( --| Checks if a list is empty.
L : in List --| List being checked.
) return Boolean;
-- Pragma Inline (Isempty);
--------------------------------------------------------------------------
function Isinlist ( --| Checks if element is an element of
--| list.
L : in List; --| list being scanned for element
Element : in Itemtype --| element being searched for
) return Boolean;
--| Effects
--| Walks down the list L looking for an element whose value is Element.
------------------------------------------------------------------------------
function Lastvalue ( --| Returns the contents of the last record of
--| the list.
L : in List --| The list whose first element is being
--| returned.
) return Itemtype;
--| Raises
--| EmptyList
--|
--| Effects
--| Returns the last element in a list. If the list is empty EmptyList is
--| raised.
------------------------------------------------------------------------------
function Length ( --| count the number of elements on a list
L : in List --| list whose length is being computed
) return Integer;
------------------------------------------------------------------------------
function Makelistiter ( --| Sets a variable to point to the head
--| of the list. This will be used to
--| prepare for iteration over a list.
L : in List --| The list being iterated over.
) return Listiter;
--| This prepares a user for iteration operation over a list. The iterater is
--| an operation which returns successive elements of the list on successive
--| calls to the iterator. There needs to be a mechanism which marks the
--| position in the list, so on successive calls to the Next operation the
--| next item in the list can be returned. This is the function of the
--| MakeListIter and the type ListIter. MakeIter just sets the Iter to the
--| the beginning of the list. On subsequent calls to Next the Iter
--| is updated with each call.
-----------------------------------------------------------------------------
function More ( --| Returns true if there are more elements in
--| the and false if there aren't any more
--| the in the list.
L : in Listiter --| List being checked for elements.
) return Boolean;
-- Pragma Inline (More);
------------------------------------------------------------------------------
procedure Next ( --| This is the iterator operation. Given
--| a ListIter in the list it returns the
--| current item and updates the ListIter.
--| If ListIter is at the end of the list,
--| More returns false otherwise it
--| returns true.
Place : in out Listiter;
--| The Iter which marks the position in
--| the list.
Info : out Itemtype --| The element being returned.
);
--| The iterators subprograms MakeListIter, More, and Next should be used
--| in the following way:
--|
--| L: List;
--| Place: ListIter;
--| Info: SomeType;
--|
--|
--| Place := MakeListIter(L);
--|
--| while ( More(Place) ) loop
--| Next(Place, Info);
--| process each element of list L;
--| end loop;
----------------------------------------------------------------------------
procedure Replacehead ( --| Replace the Item at the head of the list
--| with the parameter Item.
L : in out List; --| The list being modified.
Info : in Itemtype --| The information being entered.
);
--| Raises
--| EmptyList
--| Effects
--| Replaces the information in the first element in the list. Raises
--| EmptyList if the list is empty.
------------------------------------------------------------------------------
procedure Replacetail ( --| Replace the Tail of a list
--| with a new list.
L : in out List; --| List whose Tail is replaced.
Newtail : in List --| The list which will become the
--| tail of Oldlist.
);
--| Raises
--| EmptyList
--|
--| Effects
--| Replaces the tail of a list with a new list. If the list whose tail
--| is being replaced is null EmptyList is raised.
-------------------------------------------------------------------------------
function Tail ( --| returns the tail of a list L
L : in List --| the list whose tail is being returned
) return List;
--| Raises
--| EmptyList
--|
--| Effects
--| Returns a list which is the tail of the list L. Raises EmptyList if
--| L is empty. If L only has one element then Tail returns the Empty
--| list.
------------------------------------------------------------------------------
function Equal ( --| compares list1 and list2 for equality
List1 : in List; --| first list
List2 : in List --| second list
) return Boolean;
--| Effects
--| Returns true if for all elements of List1 the corresponding element
--| of List2 has the same value. This function uses the Equal operation
--| provided by the user. If one is not provided then = is used.
------------------------------------------------------------------------------
private
type Element_Type;
type Element_Pointer is access Element_Type;
-- type List is access element_type;
type List is
record
Head : Element_Pointer;
Tail : Element_Pointer;
end record;
type Element_Type is
record
Item : Itemtype;
Next : Element_Pointer;
end record;
type Listiter is new List; --| This prevents Lists being assigned to
--| iterators and vice versa
end Lists;
-- 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 : lr0_machine.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:30:58
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxlr0_machine.ada
-- $Header: lr0_machine.a,v 0.1 86/04/01 15:06:19 ada Exp $
-- $Log: lr0_machine.a,v $
-- Revision 0.1 86/04/01 15:06:19 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:37:14 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 Rule_Table, Symbol_Table, Set_Pack;
use Rule_Table, Symbol_Table;
package LR0_Machine is
type Parse_State is range -1..5_000;
Null_Parse_State : constant Parse_State := -1;
type Item is
record
Rule_ID : Rule;
Dot_Position : Natural;
end record;
type Transition is
record
Symbol : Grammar_Symbol;
State_ID : Parse_State;
end record;
function "<" (Item_1, Item_2 : Item) return Boolean;
function "<" (Trans_1, Trans_2 : Transition) return Boolean;
package Parse_State_Set_Pack is new Set_Pack(Parse_State, "<");
package Item_Set_Pack is new Set_Pack(Item, "<");
package Transition_Set_Pack is new Set_Pack(Transition, "<");
package Grammar_Symbol_Set_Pack is new Set_Pack(Grammar_Symbol, "<");
subtype Parse_State_Set is Parse_State_Set_Pack.Set;
subtype Item_Set is Item_Set_Pack.Set;
subtype Transition_Set is Transition_Set_Pack.Set;
subtype Grammar_Symbol_Set is Grammar_Symbol_Set_Pack.Set;
subtype Parse_State_Iterator is Parse_State_Set_Pack.Set_Iterator;
subtype Item_Iterator is Item_Set_Pack.Set_Iterator;
subtype Transition_Iterator is Transition_Set_Pack.Set_Iterator;
subtype Grammar_Symbol_Iterator is Grammar_Symbol_Set_Pack.Set_Iterator;
procedure LR0_Initialize; -- must be called first.
function First_Parse_State return Parse_State;
function Last_Parse_State return Parse_State;
function Get_Goto
(State_ID : Parse_State;
Sym : Grammar_Symbol) return Parse_State;
-- Returns the predecessor states of STATE_ID and the item I.
-- Must be called with PRED_SET empty!
procedure Get_Pred_Set
(State_ID : in Parse_State;
I : in Item;
Pred_Set : in out Parse_State_Set);
type Transition_Type is (Terminals, Nonterminals, Grammar_Symbols);
procedure Get_Transitions
(State_ID : in Parse_State;
Kind : in Transition_Type;
Set_1 : in out Transition_Set);
procedure Get_Transition_Symbols
(State_ID : in Parse_State;
Kind : in Transition_Type;
Set_1 : in out Grammar_Symbol_Set);
procedure Get_Kernel
(State_ID : in Parse_State;
Set_1 : in out Item_Set);
procedure Closure (Set_1 : in out Item_Set);
--
-- The following routines allow the user to iterate over the
-- items in the kernel of a particular state.
--
type Kernel_Iterator is limited private;
procedure Initialize
(Iterator : in out Kernel_Iterator;
State_ID : in Parse_State);
function More(Iterator : Kernel_Iterator) return Boolean;
procedure Next(Iterator : in out Kernel_Iterator; I : out Item);
--
-- The following routines allow the user to iterate over the
-- nonterminal transitions of a particular state
--
type Nt_Transition_Iterator is limited private;
procedure Initialize
(Iterator : in out Nt_Transition_Iterator;
State_ID : in Parse_State);
function More (Iterator : Nt_Transition_Iterator) return Boolean;
procedure Next
(Iterator : in out Nt_Transition_Iterator;
Trans : out Transition);
-- The following routines allow iteration over the Terminal transitions
-- of a particular state.
type T_Transition_Iterator is limited private; -- For Terminals
procedure Initialize
(Iterator : in out T_Transition_Iterator;
State_ID : in Parse_State);
function More (Iterator : T_Transition_Iterator) return Boolean;
procedure Next
(Iterator : in out T_Transition_Iterator;
Trans : out Transition);
To_Many_States : exception;
No_More_Iterations : exception;
State_Out_of_Bounds : exception;
--RJS pragma inline(more); --DEC Ada Bug: , next);
private
type Item_Array_Index is range 0..5_000; -- An arbitrarily big number
type Item_Array;
type Item_Array_Pointer is access Item_Array;
type Kernel_Iterator is
record
Kernel : Item_Array_Pointer;
Curser : Item_Array_Index;
end record;
type Transition_Array;
type Transition_Array_Pointer is access Transition_Array;
type Nt_Transition_Iterator is
record
Nonterm_Trans : Transition_Array_Pointer;
Curser : Integer; -- Use a derived type instead ???
end record;
type T_Transition_Iterator is
record
Term_Trans : Transition_Array_Pointer;
Curser : Integer;
end record;
end LR0_Machine;
-- 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 : lr0_machine_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:31:19
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxlr0_machine_body.ada
-- $Header: lr0_machine_body.a,v 0.1 86/04/01 15:06:56 ada Exp $
-- $Log: lr0_machine_body.a,v $
-- Revision 0.1 86/04/01 15:06:56 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:37:23 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 Symbol_Info, Text_IO;
use Text_IO;
package body LR0_Machine is
SCCS_ID : constant String := "@(#) lr0_machine_body.ada, Version 1.2";
use Parse_State_Set_Pack;
use Item_Set_Pack;
use Grammar_Symbol_Set_Pack;
use Transition_Set_Pack;
type Item_Array is array (Item_Array_Index range <>) of Item;
-- The type declarations for storing the nonterminal transitions of
-- the DFA in the states.
type Transition_Array is
array(Integer range <>) of Transition;
-- Note: terminal_goto is not yet used.
type State is
record
Nonterminal_Goto : Transition_Array_Pointer := null;
--& terminal_goto : transition_array_pointer := null;
Kernel : Item_Array_Pointer := null;
Preds : Parse_State_Set;
end record;
type State_Array is array (Parse_State range <>) of State;
type State_Array_Pointer is access State_Array;
--& Due to a bug in the Verdix 4.06 compiler, we cannot have the
--& 'terminal_goto' declaration in type state. (Everything will compile,
--& but when it is run we get a bus error.)
--& The following declarations are used to get around the Verdix bug.
type State_2 is
record
Terminal_Goto : Transition_Array_Pointer := null;
end record;
type State_Array_2 is array(Parse_State range <>) of State_2;
type State_Array_Pointer_2 is access State_Array_2;
State_Info_2 : State_Array_Pointer_2;
--& End of Verdix bug fix.
First_State : constant Parse_State := 0;
Last_State : Parse_State;
Max_State : Parse_State; -- estimated max
State_Info : State_Array_Pointer := null;
-- The pointer to array of state information.
Estimated_Number_of_States : Integer;
-- --
-- The following arrays are used for looking up a state given --
-- the transition symbol. TERMINAL_GOTOS holds the states that --
-- have terminal transitions into them, NONTERMINAL_GOTOS holds --
-- states that have nonterminal transitions into them and --
-- OVERFLOW_GOTOS holds the overflow from the previous arrays. --
-- --
type Goto_Array is array (Grammar_Symbol range <>) of Parse_State;
type Overflow_Array is array (Parse_State range<>) of Parse_State;
type Goto_Array_Pointer is access Goto_Array;
type Overflow_Array_Pointer is access Overflow_Array;
Terminal_Gotos : Goto_Array_Pointer;
Nonterminal_Gotos : Goto_Array_Pointer;
Overflow_Gotos : Overflow_Array_Pointer;
-- This array is used to store the items generated by get_closure
-- and closure.
-- It is also declared to work around a VADS 5.1b bug for arrays whose
-- bounds are set when the procedure is called (the memory is not
-- dealocated when the procedure is exited).
Closure_Items : Item_Array_Pointer;
type Boolean_Array is array(Grammar_Symbol range <>) of Boolean;
type Boolean_Array_Pointer is access Boolean_Array;
Examined_Symbols : Boolean_Array_Pointer;
------------------------------------------------------------------------------
function Find_State
(Kernel_Set : Item_Set;
Trans_Sym : Grammar_Symbol) return Parse_State;
function "<" (Item_1, Item_2: Item) return Boolean is
begin
if Item_1.Rule_ID = Item_2.Rule_ID then
return Item_1.Dot_Position < Item_2.Dot_Position;
else
return Item_1.Rule_ID < Item_2.Rule_ID;
end if;
end "<";
function "<" (Trans_1, Trans_2: Transition) return Boolean is
begin
if Trans_1.Symbol = Trans_2.Symbol then
return Trans_1.State_ID < Trans_2.State_ID;
else
return Trans_1.Symbol < Trans_2.Symbol;
end if;
end "<";
procedure Get_Closure
(State_ID : in Parse_State;
Closure_Items : in Item_Array_Pointer;
Last : out Item_Array_Index);
procedure Make_LR0_States is
Goto_Set : Item_Set;
Current_State : Parse_State;
Goto_State : Parse_State;
Gotos : Transition_Array_Pointer;
Nt_Trans : Transition;
Nt_Trans_Set : Transition_Set;
Nt_Trans_Iter : Transition_Iterator;
T_Trans : Transition;
T_Trans_Set : Transition_Set;
T_Trans_Iter : Transition_Iterator;
I : Item;
Sym : Grammar_Symbol;
Last : Item_Array_Index; -- The last item in closure_items.
Kernel : Item_Array_Pointer;
Did_Goto :
array(First_Symbol(Nonterminal)..Last_Symbol(Terminal)) of
Boolean; -- did_goto(sym) = True if computed goto for sym.
begin
Current_State := 0;
Generate_States:
loop
--& VADS version 4.06 corrupts memory on the following statement
--& did_goto := (others => false);
--& Therefore, we do it the hard way.
for S in Did_Goto'range loop
Did_Goto(S) := False;
end loop;
--& End bug hack.
Make_Null(Nt_Trans_Set);
Make_Null(T_Trans_Set);
Get_Closure(Current_State, Closure_Items, Last);
-- generate goto's for current state --
-- This is somewhat hacked but...
-- For simplicity, the kernel Items are appended to
-- the end of the CLOSURE_ITEMS array so that the
-- reflexive transitive closure of the state is in closure_items.
-- (GET_CLOSURE only puts the transitive closure
-- into closure_items).
-- This assumes that CLOSURE_ITEMS is large enough to hold the
-- closure + kernel. This assumtion should hold for all
-- but contrived grammars (I hope).
Kernel := State_Info(Current_State).Kernel;
for Item_Index in Kernel.all'range loop
Last := Last + 1;
Closure_Items(Last) := Kernel(Item_Index);
end loop;
for Item_Index in 1..Last loop
I := Closure_Items(Item_Index);
if I.Dot_Position < Length_of(I.Rule_ID) then
Sym := Get_RHS(I.Rule_ID, I.Dot_Position + 1);
-- generate goto on SYM if not done yet.
if not Did_Goto(Sym) then
Did_Goto(Sym) := True;
-- get the items in goto of sym
Make_Null(Goto_Set);
I.Dot_Position := I.Dot_Position + 1;
Insert(I, Into => Goto_Set);
for J in Item_Index+1..Last loop
I := Closure_Items(J);
if I.Dot_Position < Length_of(I.Rule_ID) then
I.Dot_Position := I.Dot_Position + 1;
if Get_RHS(I.Rule_ID, I.Dot_Position) = Sym
then
Insert(I, Into => Goto_Set);
end if;
end if;
end loop;
Goto_State := Find_State(Goto_Set, Sym);
Make_Null(Goto_Set);
if Is_Nonterminal(Sym) then
Nt_Trans := (Symbol => Sym, State_ID => Goto_State);
Insert(Nt_Trans, Into => Nt_Trans_Set);
else -- terminal transition
T_Trans := (Symbol => Sym, State_ID => Goto_State);
Insert(T_Trans, Into => T_Trans_Set);
end if;
Insert(Current_State,
Into => State_Info(Goto_State).Preds);
end if;
end if;
end loop;
-- at this point, all the goto's for the current
-- state have been generated.
State_Info(Current_State).Nonterminal_Goto :=
new Transition_Array(1..Size_of(Nt_Trans_Set));
Gotos := State_Info(Current_State).Nonterminal_Goto;
Initialize(Nt_Trans_Iter, Nt_Trans_Set);
for S in 1..Size_of(Nt_Trans_Set) loop
Next(Nt_Trans_Iter, Nt_Trans);
Gotos(S) := Nt_Trans;
end loop;
State_Info_2(Current_State).Terminal_Goto :=
new Transition_Array(1..Size_of(T_Trans_Set));
Gotos := State_Info_2(Current_State).Terminal_Goto;
Initialize(T_Trans_Iter, T_Trans_Set);
for S in 1..Size_of(T_Trans_Set) loop
Next(T_Trans_Iter, T_Trans);
Gotos(S) := T_Trans;
end loop;
Make_Null(Nt_Trans_Set);
Make_Null(T_Trans_Set);
Current_State := Current_State + 1;
exit Generate_States when Current_State > Last_State;
end loop Generate_States;
end Make_LR0_States;
-- This procedure allocates the arrays for computing the LR(0) states.
-- The number of states is not known at this point, so it is
-- estimated using a formula taken from
--
-- Purdom, P. W.: "The Size of LALR(1) Parsers," BIT, VOL. 14,
-- No. 3, July 1974, pp.326-337
--
-- The formula is
-- Number of states = 0.5949 * C + 0.02
--
-- where C is the number of rules plus the total number of symbols on
-- the right hand side. We round this figures a little...
procedure LR0_Initialize is
C : Integer := 0;
First_Item: constant Item := (Rule_ID => First_Rule, Dot_Position => 0);
begin
-- estimate the number of states --
for R in First_Rule..Last_Rule loop
C := C + 1 + Length_of(R);
end loop;
Estimated_Number_of_States :=
Integer(0.6 * Float(C) + 1.0);
-- Increase the estimate by 25% just in case --
Max_State := 2 + Parse_State(1.25 * Float(Estimated_Number_of_States));
if Max_State < 100 then
Max_State := 100;
end if;
-- Initialize the state array --
State_Info := new State_Array(0..Max_State);
State_Info(First_State).Kernel := new Item_Array(1..1);
State_Info(First_State).Kernel(1) := First_Item;
Make_Null(State_Info(First_State).Preds);
--& Hack state_info_2
State_Info_2 := new State_Array_2(0..Max_State);
Last_State := 0;
-- set up the goto arrays --
Terminal_Gotos := new Goto_Array
(First_Symbol(Terminal)..Last_Symbol(Terminal));
Nonterminal_Gotos := new Goto_Array
(First_Symbol(Nonterminal)..Last_Symbol(Nonterminal));
Overflow_Gotos := new Overflow_Array(First_State..Max_State);
-- Initialize them to the null_parse_state --
--& more Verdix BUGS
--& terminal_gotos.all :=
--& (terminal_gotos.all'range => null_parse_state);
--&
--& nonterminal_gotos.all :=
--& (nonterminal_gotos.all'range => null_parse_state);
--& Start Verdix bug fix
for I in Terminal_Gotos.all'range loop
Terminal_Gotos(I) := Null_Parse_State;
end loop;
for I in Nonterminal_Gotos.all'range loop
Nonterminal_Gotos(I) := Null_Parse_State;
end loop;
--& End Verdix Bug fix
-- initialize closure_items to the size of the maximum closure
-- i. e. the number of rules in the grammar.
-- Hack: The size is increased by 15 to hold any kernel that
-- might be appended to closure_items. It is hoped
-- that no kernel is greater that 15. If a kernel is greater
-- than 15, it is hoped that #rules+15 > transitive closure
-- of any state.
Closure_Items := new Item_Array
(1..Item_Array_Index(Last_Rule-First_Rule+1+15));
Examined_Symbols := new Boolean_Array
(First_Symbol(Nonterminal)..Last_Symbol(Nonterminal));
Make_LR0_States;
end LR0_Initialize;
function First_Parse_State return Parse_State is
begin
return First_State; -- a constant;
end First_Parse_State;
function Last_Parse_State return Parse_State is
begin
return Last_State;
end Last_Parse_State;
procedure Get_Closure
(State_ID : in Parse_State;
Closure_Items : in Item_Array_Pointer;
Last : out Item_Array_Index) is
---
use Symbol_Info;
Sym : Grammar_Symbol;
Iterator : Item_Iterator;
Temp_Item : Item;
New_Item : Item;
Index : Yield_Index;
Last_Index : Yield_Index;
Closure_Index : Item_Array_Index; -- for looping thru Closure_Items
Next_Free : Item_Array_Index; -- next free in closure_items
Kernel_Ptr : Item_Array_Pointer; -- points to kernel
begin
-- examined_symbols := (others => false);
for I in Examined_Symbols.all'range loop
Examined_Symbols(I) := False;
end loop;
New_Item.Dot_Position := 0; -- Used to add closure items.
Next_Free := 1;
-- first add all the items directly derivable from kernel to closure.
Kernel_Ptr := State_Info(State_ID).Kernel;
for T in Kernel_Ptr.all'range loop
Temp_Item := Kernel_Ptr(T);
if Temp_Item.Dot_Position < Length_of(Temp_Item.Rule_ID) then
Sym := Get_RHS(Temp_Item.Rule_ID, Temp_Item.Dot_Position+1);
if Is_Nonterminal(Sym) and then not Examined_Symbols(Sym) then
Examined_Symbols(Sym) := True;
for I in Nonterminal_Yield_Index(Sym)..
Nonterminal_Yield_Index(Sym+1) - 1
loop
New_Item.Rule_ID := Nonterminal_Yield(I);
Closure_Items(Next_Free) := New_Item;
Next_Free := Next_Free + 1;
end loop;
end if;
end if;
end loop;
-- Now compute the closure of the items in Closure_Items.
Closure_Index := 1;
while Closure_Index < Next_Free loop
Temp_Item := Closure_Items(Closure_Index);
if Temp_Item.Dot_Position < Length_of(Temp_Item.Rule_ID) then
Sym := Get_RHS(Temp_Item.Rule_ID, Temp_Item.Dot_Position+1);
if Is_Nonterminal(Sym) and then not Examined_Symbols(Sym) then
Examined_Symbols(Sym) := True;
for I in Nonterminal_Yield_Index(Sym)..
Nonterminal_Yield_Index(Sym+1) - 1
loop
New_Item.Rule_ID := Nonterminal_Yield(I);
Closure_Items(Next_Free) := New_Item;
Next_Free := Next_Free + 1;
end loop;
end if;
end if;
Closure_Index := Closure_Index + 1;
end loop;
Last := Next_Free - 1;
end Get_Closure;
procedure Closure(Set_1: in out Item_Set) is
use Symbol_Info;
Next_Free : Item_Array_Index; -- index of next free in Closure_Items
Sym : Grammar_Symbol;
Iterator : Item_Iterator;
Temp_Item : Item;
New_Item : Item;
Index : Yield_Index;
Last_Index : Yield_Index;
Closure_Index : Item_Array_Index; -- for looping thru Closure_Items
begin
Next_Free := 1;
-- examined_symbols := (others => false);
for I in Examined_Symbols.all'range loop
Examined_Symbols(I) := False;
end loop;
New_Item.Dot_Position := 0; -- Used to add closure items.
-- first add all the items directly derivable from set_1 to closure.
Initialize(Iterator, Set_1);
while More(Iterator) loop
Next(Iterator, Temp_Item);
if Temp_Item.Dot_Position < Length_of(Temp_Item.Rule_ID) then
Sym := Get_RHS(Temp_Item.Rule_ID, Temp_Item.Dot_Position+1);
if Is_Nonterminal(Sym) and then not Examined_Symbols(Sym) then
Examined_Symbols(Sym) := True;
for I in Nonterminal_Yield_Index(Sym)..
Nonterminal_Yield_Index(Sym+1) - 1
loop
New_Item.Rule_ID := Nonterminal_Yield(I);
Closure_Items(Next_Free) := New_Item;
Next_Free := Next_Free + 1;
end loop;
end if;
end if;
end loop;
-- Now comput the closure of the items in Closure_Items.
Closure_Index := 1;
while Closure_Index < Next_Free loop
Temp_Item := Closure_Items(Closure_Index);
if Temp_Item.Dot_Position < Length_of(Temp_Item.Rule_ID) then
Sym := Get_RHS(Temp_Item.Rule_ID, Temp_Item.Dot_Position+1);
if Is_Nonterminal(Sym) and then not Examined_Symbols(Sym) then
Examined_Symbols(Sym) := True;
for I in Nonterminal_Yield_Index(Sym)..
Nonterminal_Yield_Index(Sym+1) - 1
loop
New_Item.Rule_ID := Nonterminal_Yield(I);
Closure_Items(Next_Free) := New_Item;
Next_Free := Next_Free + 1;
end loop;
end if;
end if;
Closure_Index := Closure_Index + 1;
end loop;
-- Now add all the closure items to set_1.
for I in 1..Next_Free-1 loop
Insert(Closure_Items(I), Into => Set_1);
end loop;
end Closure;
function Find_State(Kernel_Set : Item_Set;
Trans_Sym : Grammar_Symbol) return Parse_State is
Last : constant Item_Array_Index :=
Item_Array_Index(Size_of(Kernel_Set));
Temp_Item : Item;
Iterator : Item_Set_Pack.Set_Iterator;
Kernel : Item_Array(1..Last);
S : Parse_State;
begin
if Last = 0 then
Put_Line("Ayacc: Possible Error in Find_State.");
return Null_Parse_State;
end if;
-- Copy kernel_set into the array KERNEL to compare it
-- to exiting states.
Initialize(Iterator, Kernel_Set);
for I in 1..Last loop -- last = # of items in kernel_set
Next(Iterator, Kernel(I));
end loop;
-- Look for state in existing states --
if Is_Terminal(Trans_Sym) then
S := Terminal_Gotos(Trans_Sym);
else
S := Nonterminal_Gotos(Trans_Sym);
end if;
while S /= Null_Parse_State loop
-- Uncomment the following 3 lines of code when you
-- you use a bug free compiler.
--&if kernel = state_info(S).kernel.all then
--&return S;
--&end if;
-- The following code is to fix a bug in the Verdix compiler
-- remove it when you use a bug free compiler.
if Kernel'Last /= State_Info(S).Kernel.all'Last then
goto Continue;
end if;
for J in Kernel'range loop
if Kernel(J).Rule_ID /= State_Info(S).Kernel(J).Rule_ID
or else
Kernel(J).Dot_Position /=
State_Info(S).Kernel(J).Dot_Position
then
goto Continue;
end if;
end loop;
return S;
-- The end of verdix compiler bug fix.
<<Continue>>
S := Overflow_Gotos(S);
end loop;
-- Didn't find state, create a new state. --
Last_State := Last_State + 1;
State_Info(Last_State).Kernel := new Item_Array(1..Last);
State_Info(Last_State).Kernel.all := Kernel;
Make_Null(State_Info(Last_State).Preds);
-- Save state number in list of transitions on symbol Trans_Sym.
if Is_Terminal(Trans_Sym) then
Overflow_Gotos(Last_State) := Terminal_Gotos(Trans_Sym);
Terminal_Gotos(Trans_Sym) := Last_State;
else
Overflow_Gotos(Last_State) := Nonterminal_Gotos(Trans_Sym);
Nonterminal_Gotos(Trans_Sym) := Last_State;
end if;
return Last_State;
end Find_State;
function Get_Goto(State_ID : Parse_State;
Sym : Grammar_Symbol) return Parse_State is
Gotos : Transition_Array_Pointer;
begin
Gotos := State_Info(State_ID).Nonterminal_Goto;
for S in Gotos.all'range loop
if Sym = Gotos(S).Symbol then
return Gotos(S).State_ID;
end if;
end loop;
Put_Line("Ayacc: Possible Error in Get_Goto.");
return Null_Parse_State;
end Get_Goto;
procedure Get_Pred_Set
(State_ID : in Parse_State;
I : in Item;
Pred_Set : in out Parse_State_Set) is
----
New_Item : Item;
Temp_Item : Item;
Iterator : Parse_State_Iterator;
Pred_State : Parse_State;
begin
if I.Dot_Position = 0 then
Insert(State_ID, Into => Pred_Set);
else
Temp_Item := State_Info(State_ID).Kernel(1);
if Get_RHS(Temp_Item.Rule_ID, Temp_Item.Dot_Position) =
Get_RHS(I.Rule_ID, I.Dot_Position)
then
New_Item := (I.Rule_ID, I.Dot_Position - 1);
Initialize(Iterator, State_Info(State_ID).Preds);
while More(Iterator) loop
Next(Iterator, Pred_State);
Get_Pred_Set(Pred_State, New_Item, Pred_Set);
end loop;
end if;
end if;
end Get_Pred_Set;
procedure Get_Transitions
(State_ID : in Parse_State;
Kind : in Transition_Type;
Set_1 : in out Transition_Set) is
Gotos : Transition_Array_Pointer;
begin
Make_Null(Set_1);
if Kind = Terminals or else Kind = Grammar_Symbols then
Gotos := State_Info_2(State_ID).Terminal_Goto;
for S in reverse Gotos.all'range loop
Insert(Gotos(S), Into => Set_1);
end loop;
end if;
if Kind /= Terminals then
Gotos := State_Info(State_ID).Nonterminal_Goto;
for S in reverse Gotos.all'range loop
Insert(Gotos(S), Into => Set_1);
end loop;
return;
end if;
end Get_Transitions;
procedure Get_Transition_Symbols
(State_ID : in Parse_State;
Kind : in Transition_Type;
Set_1 : in out Grammar_Symbol_Set) is
Gotos : Transition_Array_Pointer;
begin
Make_Null(Set_1);
if Kind = Terminals or else Kind = Grammar_Symbols then
Gotos := State_Info_2(State_ID).Terminal_Goto;
for S in reverse Gotos.all'range loop
Insert(Gotos(S).Symbol, Into => Set_1);
end loop;
end if;
if Kind = Terminals then return; end if;
if Kind = Nonterminals or else Kind = Grammar_Symbols then
Gotos := State_Info(State_ID).Nonterminal_Goto;
for S in reverse Gotos.all'range loop
Insert(Gotos(S).Symbol, Into => Set_1);
end loop;
end if;
end Get_Transition_Symbols;
procedure Get_Kernel
(State_ID : in Parse_State;
Set_1 : in out Item_Set) is
begin
Make_Null(Set_1);
for I in State_Info(State_ID).Kernel.all'range loop
Insert(State_Info(State_ID).Kernel(I), Into => Set_1);
end loop;
end Get_Kernel;
procedure Initialize(Iterator : in out Kernel_Iterator;
State_ID : in Parse_State) is
begin
if State_ID in First_State..Last_State then
Iterator.Kernel := State_Info(State_ID).Kernel;
Iterator.Curser := 1;
else
raise State_Out_of_Bounds;
end if;
end Initialize;
function More(Iterator: Kernel_Iterator) return Boolean is
begin
return Iterator.Curser <= Iterator.Kernel.all'Last;
end More;
procedure Next(Iterator: in out Kernel_Iterator; I : out Item) is
begin
I := Iterator.Kernel(Iterator.Curser);
Iterator.Curser := Iterator.Curser + 1;
end Next;
procedure Initialize
(Iterator : in out Nt_Transition_Iterator;
State_ID : in Parse_State) is
begin
if State_ID in First_State..Last_State then
Iterator.Nonterm_Trans := State_Info(State_ID).Nonterminal_Goto;
Iterator.Curser := 1;
else
raise State_Out_of_Bounds;
end if;
end Initialize;
function More(Iterator : Nt_Transition_Iterator) return Boolean is
begin
return Iterator.Curser <= Iterator.Nonterm_Trans.all'Last;
end More;
procedure Next
(Iterator: in out Nt_Transition_Iterator;
Trans : out Transition) is
begin
Trans := Iterator.Nonterm_Trans(Iterator.Curser);
Iterator.Curser := Iterator.Curser + 1;
end Next;
-----------------------------------------------------
-- terminal interator stuff.
procedure Initialize
(Iterator : in out T_Transition_Iterator;
State_ID : in Parse_State) is
begin
if State_ID in First_State..Last_State then
Iterator.Term_Trans := State_Info_2(State_ID).Terminal_Goto;
Iterator.Curser := 1;
else
raise State_Out_of_Bounds;
end if;
end Initialize;
function More(Iterator : T_Transition_Iterator) return Boolean is
begin
return Iterator.Curser <= Iterator.Term_Trans.all'Last;
end More;
procedure Next
(Iterator: in out T_Transition_Iterator;
Trans : out Transition) is
begin
Trans := Iterator.Term_Trans(Iterator.Curser);
Iterator.Curser := Iterator.Curser + 1;
end Next;
end LR0_Machine;
-- 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 : options.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:31:39
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxoptions.ada
-- $Header: options.a,v 0.1 86/04/01 15:08:15 ada Exp $
-- $Log: options.a,v $
-- Revision 0.1 86/04/01 15:08:15 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:37:34 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.
--
package Options is
procedure Set_Options(S: in String);
-- SET_OPTIONS sets the debug and verbose flags according
-- the the string S.
-- If S contains the characters 'v' or 'V', the verbose
-- option is set.
-- If S contains the charactars 'c' or 'C', the vebose conflicts
-- option is set.
-- If S contains the characters 'd' or 'D', the debug
-- option is set.
-- If S contains the characters 's' or 'S', the summary option
-- is set.
function Verbose return Boolean;
-- Returns TRUE if the verbose file is to be created.
function Verbose_Conflict return Boolean;
-- Returns TRUE if only the states involved in conflicts
-- are to printed.
function Debug return Boolean;
-- Returns TRUE if the YYPARSE procedure should generate
-- debugging output.
function Summary return Boolean;
-- Returns TRUE if a summary of statistics of the generated
-- parser should be printed.
function Interface_to_C return Boolean;
function Loud return Boolean;
-- Returns TRUE if Ayacc should output useless and annoying information
-- while it is running.
Illegal_Option: exception;
end Options;
package body Options is
SCCS_ID : constant String := "@(#) options.ada, Version 1.2";
Rcs_ID : constant String := "$Header: options.a,v 0.1 86/04/01 15:08:15 ada Exp $";
Verbose_Option : Boolean := False;
Verbose_Conflict_Option : Boolean := False;
Debug_Option : Boolean := False;
Interface_to_C_Option : Boolean := False;
Summary_Option : Boolean := False;
Loud_Option : Boolean := False;
procedure Set_Options(S: in String) is
begin
for I in S'First..S'Last loop
case S(I) is
when 'v' | 'V' =>
Verbose_Option := True;
when 'c' | 'C' =>
Verbose_Conflict_Option := True;
when 'd' | 'D' =>
Debug_Option := True;
when 'i' | 'I' =>
Interface_to_C_Option := True;
when 's' | 'S' =>
Summary_Option := True;
when 'l' | 'L' =>
Loud_Option := True;
when others =>
raise Illegal_Option;
end case;
end loop;
end Set_Options;
function Verbose return Boolean is
begin
return Verbose_Option;
end;
function Verbose_Conflict return Boolean is
begin
return Verbose_Conflict_Option;
end;
function Debug return Boolean is
begin
return Debug_Option;
end;
function Interface_to_C return Boolean is
begin
return Interface_to_C_Option;
end;
function Summary return Boolean is
begin
return Summary_Option;
end;
function Loud return Boolean is
begin
return Loud_Option;
end;
end Options;
-- 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 : output_file.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:31:54
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxoutput_file.ada
-- $Header: output_file.a,v 0.1 86/04/01 15:08:21 ada Exp $
-- $Log: output_file.a,v $
-- Revision 0.1 86/04/01 15:08:21 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:37:42 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.
--
-- Creates the parser
package Output_File is
procedure Make_Output_File;
end Output_File;
-- 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 : output_file_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:32:10
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxoutput_file_body.ada
-- $Header: output_file_body.a,v 0.1 86/04/01 15:08:26 ada Exp $
-- $Log: output_file_body.a,v $
-- Revision 0.1 86/04/01 15:08:26 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:37:50 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 Actions_File, File_Names, Lexical_Analyzer, Options, Parse_Table,
Parse_Template_File, Source_File, Text_IO;
use Actions_File, File_Names, Lexical_Analyzer, Options, Parse_Table,
Parse_Template_File, Source_File, Text_IO;
package body Output_File is
SCCS_ID : constant String := "@(#) output_file_body.ada, Version 1.2";
Outfile : File_Type;
procedure Open is
begin
Create(Outfile, Out_File, Get_Out_File_Name);
end Open;
procedure Close is
begin
Close(Outfile);
end Close;
-- Make the parser body section by reading the source --
-- and template files and merging them appropriately --
procedure Make_Output_File is
Text : String(1..260);
Length : Natural;
I : Integer;
begin
Open; -- Open the output file.
-- Read the first part of the source file up to '##'
-- or to end of file.
while not Source_File.Is_End_of_File loop
Source_File.Read_Line(Text, Length);
if Length > 1 then
I := 1;
while (I < Length - 1 and then Text(I) = ' ') loop
I := I + 1;
end loop;
if Text(I..I+1) = "##" then
exit;
end if;
end if;
Put_Line(Outfile, Text(1..Length));
end loop;
Parse_Template_File.Open;
-- Copy the header from the parse template
loop
Parse_Template_File.Read(Text,Length);
if Length > 1 and then Text(1..2) = "%%" then
exit;
else
Put_Line(Outfile, Text(1..Length));
end if;
end loop;
Put_Line (Outfile, " package yy_goto_tables renames");
Put_Line (Outfile, " " & Goto_Tables_Unit_Name & ';');
Put_Line (Outfile, " package yy_shift_reduce_tables renames");
Put_Line (Outfile, " " & Shift_Reduce_Tables_Unit_Name & ';');
Put_Line (Outfile, " package yy_tokens renames");
Put_Line (Outfile, " " & Tokens_Unit_Name & ';');
-- Copy the first half of the parse template
loop
Parse_Template_File.Read(Text,Length);
if Length > 1 and then Text(1..2) = "%%" then
exit;
else
Put_Line(Outfile, Text(1..Length));
end if;
end loop;
-- Copy declarations and procedures needed in the parse template
Put_Line (Outfile," DEBUG : constant boolean := " &
Boolean'Image (Options.Debug) & ';');
-- Consume Template Up To User Action Routines.
loop
Parse_Template_File.Read(Text,Length);
if Length > 1 and then Text(1..2) = "%%" then
exit;
else
Put_Line(Outfile, Text(1..Length));
end if;
end loop;
Actions_File.Open(Actions_File.Read_File);
loop
exit when Actions_File.Is_End_of_File;
Actions_File.Read_Line(Text,Length);
Put_Line(Outfile, Text(1..Length));
end loop;
Actions_File.Delete;
-- Finish writing the template file
loop
exit when Parse_Template_File.Is_End_of_File;
Parse_Template_File.Read(Text,Length);
Put_Line(Outfile, Text(1..Length));
end loop;
Parse_Template_File.Close;
-- Copy rest of input file after ##
while not Source_File.Is_End_of_File loop
Source_File.Read_Line(Text, Length);
Put_Line(Outfile, Text(1..Length));
end loop;
Close;
end Make_Output_File;
end Output_File;
-- 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 : parse_table.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:32:58
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxparse_table.ada
-- $Header: parse_table.a,v 0.1 86/04/01 15:08:33 ada Exp $
-- $Log: parse_table.a,v $
-- Revision 0.1 86/04/01 15:08:33 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:37:58 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.
--
-- This package build the shift reduce table and the goto table and
-- writes it to the shift_reduce_file, and goto_file. If the verbose option
-- is set, the states generated and their coresponding actions are written
-- to the verobose_file.
-- The parse table produced is an LALR(1) parse table.
-- The number of conflicts resulting from the grammar
-- can be determinied by calling the funciton REDUCE_REDUCE_CONFLICTS and
-- SHIFT_REDUCE_CONFLICTS, after calling MAKE_PARSE_TABLE.
package Parse_Table is
procedure Make_Parse_Table;
-- These functions must be called AFTER Make_parse_Table
function Shift_Reduce_Conflicts return Natural;
function Reduce_Reduce_Conflicts return Natural;
function Number_of_States return Natural;
function Size_of_Goto_Table return Natural;
function Size_of_Action_Table return Natural;
end Parse_Table;
-- 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 : parse_table_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:33:16
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxparse_table_body.ada
-- $Header: parse_table_body.a,v 0.1 86/04/01 15:08:38 ada Exp $
-- $Log: parse_table_body.a,v $
-- Revision 0.1 86/04/01 15:08:38 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:39:53 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 LALR_Symbol_Info, LR0_Machine, Symbol_Table, Rule_Table,
Text_IO, Symbol_Info, Verbose_File, Options, Goto_File,
Shift_Reduce_File;
use LALR_Symbol_Info, LR0_Machine, Symbol_Table, Rule_Table,
Text_IO, Symbol_Info, Options;
package body Parse_Table is
SCCS_ID : constant String := "@(#) parse_table_body.ada, Version 1.2";
Rcs_ID : constant String := "$Header: parse_table_body.a,v 0.1 86/04/01 15:08:38 ada Exp $";
Show_Verbose : Boolean; -- Set to options.verbose
--
-- The following declarations are for the "action" table.
--
type Action_Type is (Undefined, Error, Shift, Reduce, Accept_Input);
-- UNDEFINED and ERROR are the same accept you cannot replace
-- ERROR entries by a default reduction.
type Action_Table_Entry(Action : Action_Type := Undefined) is
record
case Action is
when Shift =>
State_ID : Parse_State;
when Reduce =>
Rule_ID : Rule;
when Accept_Input | Error | Undefined =>
null;
end case;
end record;
type Action_Table_Array is
array(Grammar_Symbol range <>) of Action_Table_Entry;
type Action_Table_Array_Pointer is access Action_Table_Array;
Action_Table_Row : Action_Table_Array_Pointer;
Default_Action : Action_Table_Entry;
--
-- The following declarations are for the "goto" table
--
type Goto_Table_Array is
array(Grammar_Symbol range <>) of Parse_State;
type Goto_Table_Array_Pointer is access Goto_Table_Array;
Goto_Table_Row : Goto_Table_Array_Pointer;
--
type Goto_Offset_Array is array(Parse_State range <>) of Integer;
type Goto_Offset_Array_Pointer is access Goto_Offset_Array;
Goto_Offset : Goto_Offset_Array_Pointer;
type Action_Offset_Array is array(Parse_State range <>) of Integer;
type Action_Offset_Array_Pointer is access Action_Offset_Array;
Action_Offset : Action_Offset_Array_Pointer;
--
Error_Code : constant := -1000; -- generated parser must use these
Accept_Code : constant := -1001;
Num_of_Goto_Entries : Integer := 0;
Num_of_Action_Entries : Integer := 0;
Num_Shift_Reduce_Conflicts : Natural := 0;
Num_Reduce_Reduce_Conflicts : Natural := 0;
function Shift_Reduce_Conflicts return Natural is
begin
return Num_Shift_Reduce_Conflicts;
end;
function Reduce_Reduce_Conflicts return Natural is
begin
return Num_Reduce_Reduce_Conflicts;
end;
function Number_of_States return Natural is
begin
return Natural(LR0_Machine.Last_Parse_State + 1);
end;
function Size_of_Goto_Table return Natural is
begin
return Num_of_Goto_Entries;
end;
function Size_of_Action_Table return Natural is
begin
return Num_of_Action_Entries;
end;
procedure Print_Goto_Row_Verbose is
begin
for Sym in Goto_Table_Row.all'range loop
if Goto_Table_Row(Sym) /= Null_Parse_State then
Verbose_File.Write(Ascii.Ht);
Verbose_File.Print_Grammar_Symbol(Sym);
Verbose_File.Write(" " & Ascii.Ht);
Verbose_File.Write_Line
("goto " & Parse_State'Image(Goto_Table_Row(Sym)));
end if;
end loop;
end Print_Goto_Row_Verbose;
procedure Print_Goto_Row(State: in Parse_State) is
S: Parse_State;
begin
Goto_Offset(State) := Num_of_Goto_Entries;
Goto_File.Write_Line
("-- State " & Parse_State'Image(State));
for I in Goto_Table_Row.all'range loop
S := Goto_Table_Row(I);
if S /= -1 then
Goto_File.Write(",");
Goto_File.Write("(" & Grammar_Symbol'Image(I) & "," &
Parse_State'Image(S) & ")" );
Num_of_Goto_Entries := Num_of_Goto_Entries + 1;
if Num_of_Goto_Entries mod 4 = 0 then
Goto_File.Write_Line("");
end if;
end if;
end loop;
Goto_File.Write_Line("");
end Print_Goto_Row;
-----------------------------------------------------------------------
procedure Print_Action_Row(State: in Parse_State) is
Temp : Action_Table_Entry;
X : Integer;
Default : Integer;
function Get_Default_Entry return Integer is
begin
for I in Action_Table_Row.all'range loop
if Action_Table_Row(I).Action = Reduce then
return -Integer(Action_Table_Row(I).Rule_ID);
end if;
end loop;
return Error_Code;
end Get_Default_Entry;
begin
Action_Offset(State) := Num_of_Action_Entries;
Shift_Reduce_File.Write_Line
("-- state " & Parse_State'Image(State));
Default := Get_Default_Entry;
for I in Action_Table_Row.all'range loop
Temp := Action_Table_Row(I);
case Temp.Action is
when Undefined =>
X := Default;
when Shift =>
X := Integer(Temp.State_ID);
when Reduce =>
X := - Integer(Temp.Rule_ID);
when Accept_Input =>
X := Accept_Code;
when Error =>
X := Error_Code;
end case;
if X /= Default then
Shift_Reduce_File.Write(",");
Shift_Reduce_File.Write("(" & Grammar_Symbol'Image(I) & ",");
Shift_Reduce_File.Write(Integer'Image(X) & ")" );
Num_of_Action_Entries := Num_of_Action_Entries + 1;
if Num_of_Action_Entries mod 4 = 0 then
Shift_Reduce_File.Write_Line("");
end if;
if Show_Verbose then
Verbose_File.Write(" " & Ascii.Ht);
Verbose_File.Print_Grammar_Symbol(I);
Verbose_File.Write(" " & Ascii.Ht);
if X = Accept_Code then
Verbose_File.Write_Line("accept");
elsif X = Error_Code then
Verbose_File.Write_Line("error");
elsif X > 0 then -- SHIFT
Verbose_File.Write_Line("shift " & Integer'Image(X));
else -- REDUCE
Verbose_File.Write_Line("reduce " & Integer'Image(-X));
end if;
end if;
end if;
end loop;
if Show_Verbose then
Verbose_File.Write(" " & Ascii.Ht);
Verbose_File.Write("default " & Ascii.Ht);
if Default = Accept_Code then
Verbose_File.Write_Line("accept");
elsif Default = Error_Code then
Verbose_File.Write_Line("error");
else -- reduce. never shift
Verbose_File.Write_Line("reduce " & Integer'Image(-Default));
end if;
end if;
Shift_Reduce_File.Write(",");
Shift_Reduce_File.Write("(" & Grammar_Symbol'Image(-1) & ",");
Shift_Reduce_File.Write(Integer'Image(Default) & ")" );
Num_of_Action_Entries := Num_of_Action_Entries + 1;
if Num_of_Action_Entries mod 4 = 0 then
Shift_Reduce_File.Write_Line("");
end if;
Shift_Reduce_File.Write_Line("");
end Print_Action_Row;
-----------------------------------------------------------------------
procedure Init_Table_Files is
begin
Goto_Offset := new Goto_Offset_Array
(First_Parse_State..Last_Parse_State);
Action_Offset := new Action_Offset_Array
(First_Parse_State..Last_Parse_State);
Goto_File.Open_Write;
Shift_Reduce_File.Open_Write;
end Init_Table_Files;
procedure Finish_Table_Files is
begin
Goto_File.Write_Line(");");
Goto_File.Write_Line("-- The offset vector");
Goto_File.Write("GOTO_OFFSET : array (0..");
Goto_File.Write(Parse_State'Image(Goto_Offset.all'Last) & ')');
Goto_File.Write_Line(" of Integer :=");
Goto_File.Write("(");
for I in Goto_Offset.all'First .. Goto_Offset.all'Last-1 loop
Goto_File.Write(Integer'Image(Goto_Offset(I)) & ",");
if I mod 10 = 0 then Goto_File.Write_Line(""); end if;
end loop;
Goto_File.Write
(Integer'Image(Goto_Offset(Goto_Offset.all'Last)));
Goto_File.Write_Line(");");
Goto_File.Close_Write;
Shift_Reduce_File.Write_Line(");");
Shift_Reduce_File.Write_Line("-- The offset vector");
Shift_Reduce_File.Write("SHIFT_REDUCE_OFFSET : array (0..");
Shift_Reduce_File.Write
(Parse_State'Image(Action_Offset.all'Last) & ')');
Shift_Reduce_File.Write_Line(" of Integer :=");
Shift_Reduce_File.Write("(");
for I in Action_Offset.all'First..Action_Offset.all'Last-1
loop
Shift_Reduce_File.Write
(Integer'Image(Action_Offset(I)) & ",");
if I mod 10 = 0 then Shift_Reduce_File.Write_Line(""); end if;
end loop;
Shift_Reduce_File.Write
(Integer'Image(Action_Offset(Action_Offset.all'Last)));
Shift_Reduce_File.Write_Line(");");
Shift_Reduce_File.Close_Write;
end Finish_Table_Files;
procedure Compute_Parse_Table is
use Transition_Set_Pack;
use Item_Set_Pack;
use Grammar_Symbol_Set_Pack;
Trans : Transition;
Nonterm_Iter : Nt_Transition_Iterator;
Term_Iter : T_Transition_Iterator;
Item_Set_1 : Item_Set;
Item_Iter : Item_Iterator;
Temp_Item : Item;
Lookahead_Set : Grammar_Symbol_Set;
Sym_Iter : Grammar_Symbol_Iterator;
Sym : Grammar_Symbol;
-- these variables are used for resolving conflicts
Sym_Prec : Precedence;
Rule_Prec : Precedence;
Sym_Assoc : Associativity;
-- recduce by r or action in action_table_row(sym);
procedure Report_Conflict(R: Rule; Sym : in Grammar_Symbol) is
begin
if Show_Verbose then
Verbose_File.Write("*** Conflict on input ");
Verbose_File.Print_Grammar_Symbol(Sym);
Verbose_File.Write_Line;
Verbose_File.Write(Ascii.Ht);
Verbose_File.Write("Reduce " & Rule'Image(R));
Verbose_File.Write(Ascii.Ht);
Verbose_File.Write("or");
Verbose_File.Write(Ascii.Ht);
end if;
case Action_Table_Row(Sym).Action is
when Shift =>
Num_Shift_Reduce_Conflicts :=
Num_Shift_Reduce_Conflicts + 1;
if Show_Verbose then
Verbose_File.Write("Shift ");
Verbose_File.Write_Line
(Parse_State'Image(Action_Table_Row(Sym).State_ID));
end if;
when Reduce =>
Num_Reduce_Reduce_Conflicts :=
Num_Reduce_Reduce_Conflicts + 1;
if Show_Verbose then
Verbose_File.Write("Reduce ");
Verbose_File.Write_Line
(Rule'Image(Action_Table_Row(Sym).Rule_ID));
end if;
when Accept_Input =>
if Show_Verbose then
Verbose_File.Write("Accept???"); -- won't happen
end if;
Put_Line("Ayacc: Internal Error in Report Conflict!");
when Error =>
if Show_Verbose then
Verbose_File.Write_Line("Error???"); -- won't happen
end if;
Put_Line("Ayacc: Internal Error in Report Conflict!");
when Undefined =>
Put_Line("Ayacc: Internal Error in Report Conflict!");
end case;
if Show_Verbose then
Verbose_File.Write_Line;
end if;
end;
begin
Action_Table_Row := new Action_Table_Array
(First_Symbol(Terminal)..Last_Symbol(Terminal));
Goto_Table_Row := new Goto_Table_Array
(First_Symbol(Nonterminal)..Last_Symbol(Nonterminal));
Init_Table_Files;
for S in First_Parse_State..Last_Parse_State loop
--& The verdix compiler apparently ALOCATES more memory for the following
--& assignments. We commented them out and replaced these statements by
--& the for loops
--& action_table_row.all :=
--& (action_table_row.all'range => (action => undefined));
--& goto_table_row.all :=
--& (goto_table_row.all'range => null_parse_state);
for I in Action_Table_Row.all'range loop
Action_Table_Row(I) := (Action => Undefined);
end loop;
for I in Goto_Table_Row.all'range loop
Goto_Table_Row(I) := Null_Parse_State;
end loop;
Make_Null(Item_Set_1);
Get_Kernel(S, Item_Set_1);
if Show_Verbose then
Verbose_File.Write_Line("------------------");
Verbose_File.Write_Line("State " & Parse_State'Image(S));
Verbose_File.Write_Line;
Verbose_File.Write_Line("Kernel");
Verbose_File.Print_Item_Set(Item_Set_1);
end if;
Closure(Item_Set_1);
if Show_Verbose then
Verbose_File.Write_Line;
Verbose_File.Write_Line("Closure");
Verbose_File.Print_Item_Set(Item_Set_1);
Verbose_File.Write_Line;
Verbose_File.Write_Line;
end if;
-- Make Shift Entries --
Initialize(Term_Iter, S);
while More(Term_Iter) loop
Next(Term_Iter, Trans);
if Trans.Symbol = End_Symbol then
Action_Table_Row(Trans.Symbol) :=
(Action => Accept_Input);
else
Action_Table_Row(Trans.Symbol) :=
(Action => Shift, State_ID => Trans.State_ID);
end if;
end loop;
-- Make Goto Entries --
Initialize(Nonterm_Iter, S);
while More(Nonterm_Iter) loop
Next(Nonterm_Iter, Trans);
Goto_Table_Row(Trans.Symbol) := Trans.State_ID;
end loop;
-- Make Reduce Entries ----
Initialize(Item_Iter, Item_Set_1);
-- check for degenerate reduce --
if Size_of(Item_Set_1) = 1 then
Next(Item_Iter, Temp_Item);
if Temp_Item.Dot_Position = Length_of(Temp_Item.Rule_ID)
and then Temp_Item.Rule_ID /= First_Rule
then
Action_Table_Row(First_Symbol(Terminal)) :=
(Action => Reduce,
Rule_ID => Temp_Item.Rule_ID);
end if;
goto Continue_Loop;
end if;
-- The following is really messy. It used to be ok before
-- we added precedence. Some day we should rewrite it.
while More(Item_Iter) loop
Next(Item_Iter, Temp_Item);
if Temp_Item.Dot_Position = Length_of(Temp_Item.Rule_ID)
and then Temp_Item.Rule_ID /= First_Rule
then
Make_Null(Lookahead_Set);
Get_LA(S, Temp_Item, Lookahead_Set);
Initialize(Sym_Iter, Lookahead_Set);
while More(Sym_Iter) loop
Next(Sym_Iter, Sym);
case Action_Table_Row(Sym).Action is
when Undefined =>
Action_Table_Row(Sym) :=
(Action => Reduce,
Rule_ID => Temp_Item.Rule_ID);
when Shift =>
Sym_Prec :=
Get_Precedence(Sym);
Rule_Prec :=
Get_Rule_Precedence(Temp_Item.Rule_ID);
if Sym_Prec = 0 or else Rule_Prec = 0 then
Report_Conflict(Temp_Item.Rule_ID, Sym);
elsif Rule_Prec > Sym_Prec then
Action_Table_Row(Sym) :=
(Action => Reduce,
Rule_ID => Temp_Item.Rule_ID);
elsif Sym_Prec > Rule_Prec then
null; -- already ok
else
Sym_Assoc :=
Get_Associativity(Sym);
if Sym_Assoc = Left_Associative then
Action_Table_Row(Sym) :=
(Action => Reduce,
Rule_ID => Temp_Item.Rule_ID);
elsif Sym_Assoc = Right_Associative then
null;
elsif Sym_Assoc = Nonassociative then
Action_Table_Row(Sym) :=
(Action => Error);
else
Put_Line("Ayacc: Possible Error in " &
"Conflict Resolution.");
end if;
end if;
when Reduce =>
Report_Conflict(Temp_Item.Rule_ID, Sym);
when Error =>
Put_Line("Ayacc: Internal Error in Conflict!!!");
Put_Line("Ayacc: Use Verbose Option!");
Report_Conflict(Temp_Item.Rule_ID, Sym);
when Accept_Input =>
Put_Line("Ayacc: Internal Error in Conflict!!!");
Put_Line("Ayacc: Use Verbose Option!");
Report_Conflict(Temp_Item.Rule_ID, Sym);
end case;
end loop;
end if;
end loop;
<<Continue_Loop>>
if Show_Verbose then
Print_Goto_Row_Verbose;
end if;
Print_Goto_Row(S);
Print_Action_Row(S);
end loop;
Finish_Table_Files;
end Compute_Parse_Table;
procedure Make_Parse_Table is
begin
Show_Verbose := Options.Verbose;
if Show_Verbose then
Verbose_File.Open;
end if;
Symbol_Info.Initialize;
if Options.Loud then
Put_Line("Ayacc: Making LR(0) Machine.");
end if;
LR0_Machine.LR0_Initialize;
if Options.Loud then
Put_Line("Ayacc: Making Follow Sets.");
end if;
Make_LALR_Sets;
if Options.Loud then
Put_Line("Ayacc: Making Parse Table.");
end if;
Compute_Parse_Table;
if Show_Verbose then
Verbose_File.Close;
end if;
end Make_Parse_Table;
end Parse_Table;
-- 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 : parse_template_file.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:33:32
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxparse_template_file.ada
-- $Header: parse_template_file.a,v 0.1 86/04/01 15:09:47 ada Exp $
-- $Log: parse_template_file.a,v $
-- Revision 0.1 86/04/01 15:09:47 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:40:09 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 Text_IO, File_Names;
use Text_IO, File_Names;
with String_Pkg; use String_Pkg;
package body Parse_Template_File is
SCCS_ID : constant String := "@(#) parse_template_file.ada, Version 1.2";
Rcs_ID : constant String := "$Header: parse_template_file.a,v 0.1 86/04/01 15:09:47 ada Exp $";
File_Pointer : Natural := 0;
type File_Data is array (Positive range <>) of String_Type;
-- Verdix 5.2 Compiler Bug will not accept aggregate size as implied constraint
-->> YYParse_Template_File : File_Data :=
-- Verdix 5.2 Compiler Bug
YYParse_Template_File : File_Data (1 .. 262) :=
( -- Start of File Contents
Create ("procedure YYParse is"),
Create (""),
Create (" -- Rename User Defined Packages to Internal Names."),
Create ("%%"),
Create (""),
Create (" use yy_tokens, yy_goto_tables, yy_shift_reduce_tables;"),
Create (""),
Create (" procedure yyerrok;"),
Create (" procedure yyclearin;"),
Create (""),
Create (" package yy is"),
Create (""),
Create (" -- the size of the value and state stacks"),
Create (" stack_size : constant Natural := 300;"),
Create (""),
Create (" -- subtype rule is natural;"),
Create (" subtype parse_state is natural;"),
Create (" -- subtype nonterminal is integer;"),
Create (""),
Create (" -- encryption constants"),
Create (" default : constant := -1;"),
Create (" first_shift_entry : constant := 0;"),
Create (" accept_code : constant := -1001;"),
Create (" error_code : constant := -1000;"),
Create (""),
Create (" -- stack data used by the parser"),
Create (" tos : natural := 0;"),
Create (" value_stack : array(0..stack_size) of yy_tokens.yystype;"),
Create (" state_stack : array(0..stack_size) of parse_state;"),
Create (""),
Create (" -- current input symbol and action the parser is on"),
Create (" action : integer;"),
Create (" rule_id : rule;"),
Create (" input_symbol : yy_tokens.token;"),
Create (""),
Create (""),
Create (" -- error recovery flag"),
Create (" error_flag : natural := 0;"),
Create (" -- indicates 3 - (number of valid shifts after an error occurs)"),
Create (""),
Create (" look_ahead : boolean := true;"),
Create (" index : integer;"),
Create (""),
Create (" -- Is Debugging option on or off"),
Create ("%%"),
Create (""),
Create (" end yy;"),
Create (""),
Create (""),
Create (" function goto_state"),
Create (" (state : yy.parse_state;"),
Create (" sym : nonterminal) return yy.parse_state;"),
Create (""),
Create (" function parse_action"),
Create (" (state : yy.parse_state;"),
Create (" t : yy_tokens.token) return integer;"),
Create (""),
Create (" pragma inline(goto_state, parse_action);"),
Create (""),
Create (""),
Create (" function goto_state(state : yy.parse_state;"),
Create (" sym : nonterminal) return yy.parse_state is"),
Create (" index : integer;"),
Create (" begin"),
Create (" index := goto_offset(state);"),
Create (" while integer(goto_matrix(index).nonterm) /= sym loop"),
Create (" index := index + 1;"),
Create (" end loop;"),
Create (" return integer(goto_matrix(index).newstate);"),
Create (" end goto_state;"),
Create (""),
Create (""),
Create (" function parse_action(state : yy.parse_state;"),
Create (" t : yy_tokens.token) return integer is"),
Create (" index : integer;"),
Create (" tok_pos : integer;"),
Create (" default : constant integer := -1;"),
Create (" begin"),
Create (" tok_pos := yy_tokens.token'pos(t);"),
Create (" index := shift_reduce_offset(state);"),
Create (" while integer(shift_reduce_matrix(index).t) /= tok_pos and then"),
Create (" integer(shift_reduce_matrix(index).t) /= default"),
Create (" loop"),
Create (" index := index + 1;"),
Create (" end loop;"),
Create (" return integer(shift_reduce_matrix(index).act);"),
Create (" end parse_action;"),
Create (""),
Create ("-- error recovery stuff"),
Create (""),
Create (" procedure handle_error is"),
Create (" temp_action : integer;"),
Create (" begin"),
Create (""),
Create (" if yy.error_flag = 3 then -- no shift yet, clobber input."),
Create (" if yy.debug then"),
Create (" put_line(""Ayacc.YYParse: Error Recovery Clobbers "" &"),
Create (" yy_tokens.token'image(yy.input_symbol));"),
Create (" end if;"),
Create (" if yy.input_symbol = yy_tokens.end_of_input then -- don't discard,"),
Create (" if yy.debug then"),
Create (" put_line(""Ayacc.YYParse: Can't discard END_OF_INPUT, quiting..."");"),
Create (" end if;"),
Create (" raise yy_tokens.syntax_error;"),
Create (" end if;"),
Create (""),
Create (" yy.look_ahead := true; -- get next token"),
Create (" return; -- and try again..."),
Create (" end if;"),
Create (""),
Create (" if yy.error_flag = 0 then -- brand new error"),
Create (" yyerror(""Syntax Error"");"),
Create (" end if;"),
Create (""),
Create (" yy.error_flag := 3;"),
Create (""),
Create (" -- find state on stack where error is a valid shift --"),
Create (""),
Create (" if yy.debug then"),
Create (" put_line(""Ayacc.YYParse: Looking for state with error as valid shift"");"),
Create (" end if;"),
Create (""),
Create (" loop"),
Create (" if yy.debug then"),
Create (" put_line(""Ayacc.YYParse: Examining State "" &"),
Create (" yy.parse_state'image(yy.state_stack(yy.tos)));"),
Create (" end if;"),
Create (" temp_action := parse_action(yy.state_stack(yy.tos), error);"),
Create (""),
Create (" if temp_action >= yy.first_shift_entry then"),
Create (" yy.tos := yy.tos + 1;"),
Create (" yy.state_stack(yy.tos) := temp_action;"),
Create (" exit;"),
Create (" end if;"),
Create (""),
Create (" Decrement_Stack_Pointer :"),
Create (" begin"),
Create (" yy.tos := yy.tos - 1;"),
Create (" exception"),
Create (" when Constraint_Error =>"),
Create (" yy.tos := 0;"),
Create (" end Decrement_Stack_Pointer;"),
Create (""),
Create (" if yy.tos = 0 then"),
Create (" if yy.debug then"),
Create (" put_line(""Ayacc.YYParse: Error recovery popped entire stack, aborting..."");"),
Create (" end if;"),
Create (" raise yy_tokens.syntax_error;"),
Create (" end if;"),
Create (" end loop;"),
Create (""),
Create (" if yy.debug then"),
Create (" put_line(""Ayacc.YYParse: Shifted error token in state "" &"),
Create (" yy.parse_state'image(yy.state_stack(yy.tos)));"),
Create (" end if;"),
Create (""),
Create (" end handle_error;"),
Create (""),
Create (" -- print debugging information for a shift operation"),
Create (" procedure shift_debug(state_id: yy.parse_state; lexeme: yy_tokens.token) is"),
Create (" begin"),
Create (" put_line(""Ayacc.YYParse: Shift ""& yy.parse_state'image(state_id)&"" on input symbol ""&"),
Create (" yy_tokens.token'image(lexeme) );"),
Create (" end;"),
Create (""),
Create (" -- print debugging information for a reduce operation"),
Create (" procedure reduce_debug(rule_id: rule; state_id: yy.parse_state) is"),
Create (" begin"),
Create (" put_line(""Ayacc.YYParse: Reduce by rule ""&rule'image(rule_id)&"" goto state ""&"),
Create (" yy.parse_state'image(state_id));"),
Create (" end;"),
Create (""),
Create (" -- make the parser believe that 3 valid shifts have occured."),
Create (" -- used for error recovery."),
Create (" procedure yyerrok is"),
Create (" begin"),
Create (" yy.error_flag := 0;"),
Create (" end yyerrok;"),
Create (""),
Create (" -- called to clear input symbol that caused an error."),
Create (" procedure yyclearin is"),
Create (" begin"),
Create (" -- yy.input_symbol := yylex;"),
Create (" yy.look_ahead := true;"),
Create (" end yyclearin;"),
Create (""),
Create (""),
Create ("begin"),
Create (" -- initialize by pushing state 0 and getting the first input symbol"),
Create (" yy.state_stack(yy.tos) := 0;"),
Create (""),
Create (" loop"),
Create (""),
Create (" yy.index := shift_reduce_offset(yy.state_stack(yy.tos));"),
Create (" if integer(shift_reduce_matrix(yy.index).t) = yy.default then"),
Create (" yy.action := integer(shift_reduce_matrix(yy.index).act);"),
Create (" else"),
Create (" if yy.look_ahead then"),
Create (" yy.look_ahead := false;"),
Create (" yy.input_symbol := yylex;"),
Create (" end if;"),
Create (" yy.action :="),
Create (" parse_action(yy.state_stack(yy.tos), yy.input_symbol);"),
Create (" end if;"),
Create (""),
Create (" if yy.action >= yy.first_shift_entry then -- SHIFT"),
Create (""),
Create (" if yy.debug then"),
Create (" shift_debug(yy.action, yy.input_symbol);"),
Create (" end if;"),
Create (""),
Create (" -- Enter new state"),
Create (" yy.tos := yy.tos + 1;"),
Create (" yy.state_stack(yy.tos) := yy.action;"),
Create (" yy.value_stack(yy.tos) := yylval;"),
Create (""),
Create (" if yy.error_flag > 0 then -- indicate a valid shift"),
Create (" yy.error_flag := yy.error_flag - 1;"),
Create (" end if;"),
Create (""),
Create (" -- Advance lookahead"),
Create (" yy.look_ahead := true;"),
Create (""),
Create (" elsif yy.action = yy.error_code then -- ERROR"),
Create (" handle_error;"),
Create (""),
Create (" elsif yy.action = yy.accept_code then"),
Create (" if yy.debug then"),
Create (" put_line(""Ayacc.YYParse: Accepting Grammar..."");"),
Create (" end if;"),
Create (" exit;"),
Create (""),
Create (" else -- Reduce Action"),
Create (""),
Create (" -- Convert action into a rule"),
Create (" yy.rule_id := -1 * yy.action;"),
Create (""),
Create (" -- Execute User Action"),
Create (" -- user_action(yy.rule_id);"),
Create (" case yy.rule_id is"),
Create ("%%"),
Create (""),
Create (" when others => null;"),
Create (" end case;"),
Create (""),
Create (" -- Pop RHS states and goto next state"),
Create (" yy.tos := yy.tos - rule_length(yy.rule_id) + 1;"),
Create (" yy.state_stack(yy.tos) := goto_state(yy.state_stack(yy.tos-1) ,"),
Create (" get_lhs_rule(yy.rule_id));"),
Create (""),
Create (" yy.value_stack(yy.tos) := yyval;"),
Create (""),
Create (" if yy.debug then"),
Create (" reduce_debug(yy.rule_id,"),
Create (" goto_state(yy.state_stack(yy.tos - 1),"),
Create (" get_lhs_rule(yy.rule_id)));"),
Create (" end if;"),
Create (""),
Create (" end if;"),
Create (" end loop;"),
Create (""),
Create ("end yyparse;") ); -- End of File Contents
procedure Open is
begin
File_Pointer := YYParse_Template_File'First;
end Open;
procedure Close is
begin
File_Pointer := 0;
end Close;
procedure Read (S: out String; Length : out Integer) is
Next_Line : constant String :=
String_Pkg.Value (YYParse_Template_File (File_Pointer));
begin
S := Next_Line & (1 .. S'Length - Next_Line'Length => ' ');
Length := Next_Line'Length;
File_Pointer := File_Pointer + 1;
exception
when Constraint_Error =>
if Is_End_of_File then
raise End_Error;
else
raise Status_Error;
end if;
end;
function Is_End_of_File return Boolean is
begin
return File_Pointer = (YYParse_Template_File'Last + 1);
end Is_End_of_File;
end Parse_Template_File;
-- 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 : parse_template_file_.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:33:46
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxparse_template_file_.ada
-- $Header: parse_template_file.a,v 0.1 86/04/01 15:09:47 ada Exp $
-- $Log: parse_template_file.a,v $
-- Revision 0.1 86/04/01 15:09:47 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:40:09 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.
--
package Parse_Template_File is
Eof : constant Character := Ascii.Nul;
procedure Open;
procedure Read (S: out String; Length : out Integer);
procedure Close;
function Is_End_of_File return Boolean;
end Parse_Template_File;
-- 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 : parser.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:32:26
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxparser.ada
-- $Header: parser.a,v 0.1 86/04/01 15:10:10 ada Exp $
-- $Log: parser.a,v $
-- Revision 0.1 86/04/01 15:10:10 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:40:20 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.
--
-- --
-- The parser for the user source file --
-- --
package Parser is
-- Parse the declarations section
procedure Parse_Declarations;
-- Parse the rules section
procedure Parse_Rules;
-- Self-explanatory
Syntax_Error : exception;
end;
-- 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 : parser_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:32:43
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxparser_body.ada
-- $Header: parser_body.a,v 0.1 86/04/01 15:10:24 ada Exp $
-- $Log: parser_body.a,v $
-- Revision 0.1 86/04/01 15:10:24 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:40:31 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.
--
-- --
-- The body of the parser for the specification file --
-- --
with Text_IO; use Text_IO;
with Lexical_Analyzer; use Lexical_Analyzer;
with STR_Pack; use STR_Pack;
with Symbol_Table; use Symbol_Table;
with Rule_Table; use Rule_Table;
with Actions_File; use Actions_File;
with Tokens_File; use Tokens_File;
with String_Pkg;
package body Parser is
SCCS_ID : constant String := "@(#) parser_body.ada, Version 1.2";
Found_Error : Boolean := False;
Start_Defined : Boolean := False;
procedure Nonfatal_Error(Message: in String) is
begin
Print_Context_Lines;
--RJS Put_Line("--- " & Message);
New_Line;
Put_Line ("Ayacc: " & Message);
Found_Error := True;
end Nonfatal_Error;
procedure Fatal_Error(Message: in String) is
begin
Print_Context_Lines;
--RJS Put_Line("--- " & Message);
New_Line;
Put_Line ("Ayacc: " & Message);
raise Syntax_Error;
end Fatal_Error;
procedure Augment_Grammar(Users_Start_Symbol : in Grammar_Symbol) is
-- Inserts S' -> S $end as a rule in the rule table.
Start_Sym : Grammar_Symbol;
Augmented_Rule : Rule;
begin
Start_Defined := True;
Augmented_Rule := Make_Rule(Start_Symbol);
Append_RHS(Augmented_Rule, Users_Start_Symbol);
Append_RHS(Augmented_Rule, End_Symbol);
end Augment_Grammar;
-- --
-- A recursive descent parser for the rules in the --
-- grammar. --
procedure Parse_Rules is
T : Ayacc_Token;
Current_Rule : Rule;
LHS : Grammar_Symbol;
-- --
-- Gets an action from the file and writes it to --
-- the actions file. --
-- --
-- --
-- Parses a sequence of Symbols --
-- --
procedure Symbols is
ID : Grammar_Symbol;
Got_Action : Boolean := False;
Precedence_Level : Precedence;
begin
loop
T := Get_Token;
exit when T = Vertical_Bar or T = Semicolon or T = Prec;
-- Do we have an action in the middle of a rule?
if Got_Action then
Got_Action := T = Left_Brace;
Handle_Nested_Rule(Current_Rule);
end if;
case T is
-- Update the current rule
when Character_Literal =>
ID := Insert_Terminal(Get_Lexeme_Text);
Append_RHS(Current_Rule, ID);
-- Update the current rule and add to symbol table
when Identifier =>
ID := Insert_Identifier(Get_Lexeme_Text);
Append_RHS(Current_Rule, ID);
-- Got an action
when Left_Brace =>
Handle_Action(Integer(Current_Rule),
Integer(Length_of(Current_Rule)));
Got_Action := True;
when others =>
Fatal_Error("Unexpected symbol");
end case;
end loop;
if T = Prec then
if Got_Action then
Fatal_Error("%prec cannot be preceded by an action");
raise Syntax_Error;
end if;
T := Get_Token;
if T /= Identifier and T /= Character_Literal then
Fatal_Error("Expecting a terminal after %prec");
end if;
ID := Insert_Identifier(Get_Lexeme_Text);
if Is_Nonterminal(ID) then
Fatal_Error("Expecting a terminal after %prec");
end if;
Precedence_Level := Get_Precedence(ID);
if Precedence_Level = 0 then
Fatal_Error("Terminal following %prec has no precedence");
else
Set_Rule_Precedence(Current_Rule, Precedence_Level);
end if;
T := Get_Token;
case T is
when Left_Brace =>
Handle_Action(Integer(Current_Rule),
Integer(Length_of(Current_Rule)));
T := Get_Token;
when Semicolon | Vertical_Bar =>
null;
when others =>
Fatal_Error("Illegal token following %prec");
end case;
end if;
end Symbols;
-- --
-- Parse an ayacc grammar rule --
-- --
procedure Rule is
begin
T := Get_Token;
if T /= Colon then
Fatal_Error("Expecting a colon after the LHS of the rule");
else
Current_Rule := Make_Rule(LHS);
Symbols;
end if;
while (T = Vertical_Bar) loop
-- Make a new rule with the current LHS grammar symbol
Current_Rule := Make_Rule(LHS);
Symbols;
end loop;
if T /= Semicolon then
Fatal_Error("Expecting a semicolon");
end if;
end Rule;
-- --
-- Parse a sequence of grammar rules --
-- --
procedure Rules is
begin
T := Get_Token;
if T = Identifier then
-- Make the left hand side of the rule
LHS := Insert_Identifier(Get_Lexeme_Text);
if Is_Terminal(LHS) then
Fatal_Error("Terminals cannot be on the LHS of a rule");
end if;
if not Start_Defined then
Augment_Grammar(LHS);
end if;
Rule;
Rules;
elsif T /= Mark then
Fatal_Error("Expecting next section");
end if;
end Rules;
begin -- parse_rules
Actions_File.Initialize;
Rules;
Actions_File.Finish;
-- Check for empty grammars. If the grammar is empty then
-- create a rule S -> $end.
if not Start_Defined then
Append_RHS(Make_Rule(Start_Symbol), End_Symbol);
end if;
exception
when Illegal_Token =>
Fatal_Error("illegal token");
end Parse_Rules;
-- --
-- Parse the declarations section of the source --
-- --
procedure Parse_Declarations is
Precedence_Level : Precedence := 0;
Next_Token : Ayacc_Token;
ID : Grammar_Symbol;
procedure Parse_Start_Symbol is
Users_Start_Symbol : Grammar_Symbol;
begin
if Start_Defined then
Fatal_Error("The start symbol has been defined already.");
end if;
if Next_Token /= Identifier then
if Next_Token = Lexical_Analyzer.Eof_Token then
Fatal_Error("Unexpected end of file before first '%%'");
else
Fatal_Error("Expecting identifier");
end if;
end if;
Users_Start_Symbol := Insert_Identifier(Get_Lexeme_Text);
if Is_Nonterminal(Users_Start_Symbol) then
Augment_Grammar(Users_Start_Symbol);
else
Fatal_Error("Attempt to define terminal as start_symbol");
end if;
Next_Token := Get_Token;
end Parse_Start_Symbol;
procedure Parse_Token_List(Precedence_Value : in Precedence;
Associativity_Value : in Associativity) is
Temp_Sym : Grammar_Symbol;
begin
loop
if Next_Token /= Identifier and then
Next_Token /= Character_Literal then
if Next_Token = Lexical_Analyzer.Eof_Token then
Fatal_Error("Unexpected end of file before first '%%'");
else
Fatal_Error("Expecting token declaration");
end if;
end if;
Temp_Sym := Insert_Terminal(Get_Lexeme_Text,
Precedence_Value,
Associativity_Value);
Next_Token := Get_Token;
if Next_Token = Comma then
Next_Token := Get_Token;
elsif Next_Token = Semicolon then
Next_Token := Get_Token;
exit;
elsif Next_Token /= Identifier and then
Next_Token /= Character_Literal then
exit;
end if;
end loop;
exception
when Illegal_Entry =>
-- I think only trying to insert the "start symbol"
-- in a token list will cause this exception
Fatal_Error("Illegal symbol as token");
end Parse_Token_List;
procedure Parse_Package_Name_List(Context_Clause : in Ayacc_Token) is
use String_Pkg;
begin
if Tokens_Package_Header_Has_Been_Generated then
Fatal_Error ("Context Clause Specifications May Not " &
"Appear After Ada Declarations.");
else
case Context_Clause is
when With_Clause =>
Tokens_File.Write ("with ");
when Use_Clause =>
Tokens_File.Write ("use ");
when others =>
Fatal_Error ("Illegal Context Clause Specification");
end case;
loop
if Next_Token /= Identifier then
if Next_Token = Lexical_Analyzer.Eof_Token then
Fatal_Error("Unexpected end of file before first '%%'");
else
Fatal_Error("Expecting Package Name");
end if;
end if;
Tokens_File.Write (' ' & Value (Mixed (Get_Lexeme_Text)));
Next_Token := Get_Token;
if Next_Token = Comma then
Next_Token := Get_Token;
Tokens_File.Write (",");
elsif Next_Token = Semicolon then
Next_Token := Get_Token;
Tokens_File.Writeln (";");
exit;
elsif Next_Token /= Identifier then
Tokens_File.Writeln (";");
exit;
else
Tokens_File.Write (",");
end if;
end loop;
end if;
end Parse_Package_Name_List;
begin
Next_Token := Get_Token;
loop
case Next_Token is
when Start =>
Next_Token := Get_Token;
Parse_Start_Symbol;
if Next_Token = Semicolon then
Next_Token := Get_Token;
end if;
when Token =>
Next_Token := Get_Token;
Parse_Token_List(0, Undefined);
when Nonassoc =>
Next_Token := Get_Token;
Precedence_Level := Precedence_Level + 1;
Parse_Token_List(Precedence_Level, Nonassociative);
when Right =>
Next_Token := Get_Token;
Precedence_Level := Precedence_Level + 1;
Parse_Token_List(Precedence_Level, Right_Associative);
when Left =>
Next_Token := Get_Token;
Precedence_Level := Precedence_Level + 1;
Parse_Token_List(Precedence_Level, Left_Associative);
when Mark =>
exit;
when Lexical_Analyzer.Eof_Token =>
Fatal_Error("Unexpected end of file before first %%");
when Left_Brace =>
Start_Tokens_Package;
Dump_Declarations; -- to the TOKENS file.
Next_Token := Get_Token;
when With_Clause =>
Next_Token := Get_Token;
Parse_Package_Name_List (With_Clause);
when Use_Clause =>
Next_Token := Get_Token;
Parse_Package_Name_List (Use_Clause);
when others =>
Fatal_Error("Unexpected symbol");
end case;
end loop;
exception
when Illegal_Token =>
Fatal_Error("Bad symbol");
when Redefined_Precedence_Error =>
Fatal_Error("Attempt to redefine precedence");
end Parse_Declarations;
end Parser;
-- 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 : ragged.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:34:00
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxragged.ada
-- $Header: ragged.a,v 0.1 86/04/01 15:11:22 ada Exp $
-- $Log: ragged.a,v $
-- Revision 0.1 86/04/01 15:11:22 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:40:45 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.
--
-- Remeber to get rid of rval as soon as all bugs have been eliminated
-- from routines that use this package.
generic
type Row_Index is (<>);
type Col_Index is (<>);
type Item is limited private;
with procedure Null_Value(Value : in out Item);
package Ragged is
-- Cell and index should be private but for efficency and for subtle
-- problems that arise when type item is implemeted as a limited private
-- in an external package, cell and index are kept visible.
type Cell;
type Index is access Cell;
pragma Controlled(Index);
type Hidden_Type is limited private;
type Cell is
record
Value : Item;
Hidden : Hidden_Type;
end record;
-- Use for retrieving the value of array(x,y). Raises value range
-- error if no such location has been allocated yet.
-- eg: value := rval(x,y).value;
function Rval(X: Row_Index; Y: Col_Index) return Index;
-- Use for setting a value in array(x,y). Allocates new storage
-- if the location does not exist yet. Can also use it if you
-- require a preinitialization value
-- eg: lval(x,y).value := value;
-- if lval(x,y).value = 0 then ...
function Lval(X: Row_Index; Y: Col_Index) return Index;
procedure Make_Array(Lower, Upper: Row_Index);
procedure Initialize(Iterator : out Index; Row : Row_Index);
procedure Next(Iterator : in out Index);
procedure Free_Array;
Value_Range_Error : exception;
private
type Hidden_Type is
record
Column : Col_Index;
Next : Index;
end record;
end Ragged;
with Unchecked_Deallocation;
package body Ragged is
SCCS_ID : constant String := "@(#) ragged.ada, Version 1.2";
-- The ragged array is implemented as a vector indexed by row
-- of linked lists of (column,value) pairs in sorted order.
type Cells is array( Row_Index range<> ) of Index;
type Cells_Ptr is access Cells;
pragma Controlled(Cells_Ptr);
Vector : Cells_Ptr;
procedure Make_Array(Lower, Upper: Row_Index) is
begin
Vector := new Cells(Lower..Upper);
for I in Vector.all'range loop
Vector(I) := null;
end loop;
end Make_Array;
function New_Cell(Column : Col_Index; Next : Index) return Index is
Temp : Index;
begin
Temp := new Cell;
Temp.Hidden.Column := Column;
Temp.Hidden.Next := Next;
-- Will this work or do I need to null_value vector ?
Null_Value(Temp.Value);
return Temp;
end New_Cell;
function Lval(X: Row_Index; Y: Col_Index) return Index is
Ptr, Last : Index;
begin
-- If a new cell is created its value field is uninitialized.
-- Add to the beginning of the list ?
if Vector(X) = null or else Vector(X).Hidden.Column > Y then
Ptr := Vector(X);
Vector(X) := New_Cell(Y,Ptr);
return Vector(X);
end if;
-- Add in the middle of the list ?
Ptr := Vector(X);
while Ptr /= null loop
if Ptr.Hidden.Column = Y then
return Ptr;
elsif Ptr.Hidden.Column > Y then
Last.Hidden.Next := New_Cell(Y,Ptr);
return Last.Hidden.Next;
end if;
Last := Ptr;
Ptr := Ptr.Hidden.Next;
end loop;
-- Add at the end of the list
Last.Hidden.Next := New_Cell(Y,null);
return Last.Hidden.Next;
end Lval;
function Rval(X: Row_Index; Y: Col_Index) return Index is
Ptr : Index;
begin
Ptr := Vector(X);
while Ptr /= null and then Ptr.Hidden.Column < Y loop
Ptr := Ptr.Hidden.Next;
end loop;
if Ptr = null or else Ptr.Hidden.Column > Y then
raise Value_Range_Error;
else -- ptr.hidden.column = y
return Ptr;
end if;
end Rval;
procedure Initialize(Iterator : out Index; Row : Row_Index) is
begin
Iterator := Vector(Row);
end;
procedure Next(Iterator : in out Index) is
begin
Iterator := Iterator.Hidden.Next;
end;
-- procedure free(i: index);
-- pragma interface(c,free);
procedure Free is new Unchecked_Deallocation(Cell, Index);
procedure Free is new Unchecked_Deallocation(Cells, Cells_Ptr);
procedure Free_Array is
Traverse : Index;
begin
for I in Vector.all'range loop
while Vector(I) /= null loop
Traverse := Vector(I);
Vector(I) := Vector(I).Hidden.Next;
Null_Value(Traverse.Value); -- free value if its a ptr
Free(Traverse);
end loop;
end loop;
Free(Vector);
end Free_Array;
end Ragged;
-- 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 : rule_table.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:34:14
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxrule_table.ada
-- $Header: rule_table.a,v 0.1 86/04/01 15:11:37 ada Exp $
-- $Log: rule_table.a,v $
-- Revision 0.1 86/04/01 15:11:37 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:40:56 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 Symbol_Table;
use Symbol_Table;
package Rule_Table is
-- This package is used to store and access the rules
-- of the input grammar.
Max_Rules : constant := 1_000; -- An arbitrary upper bound.
type Rule is range 0..Max_Rules - 1;
function Make_Rule(LHS: Grammar_Symbol) return Rule;
procedure Append_RHS(R: in Rule; RHS: in Grammar_Symbol);
function Get_LHS (R: Rule) return Grammar_Symbol;
function Get_RHS (R: Rule; Position: Positive) return Grammar_Symbol;
function Get_Null_Pos (R: Rule) return Natural;
function Get_Rule_Precedence (R: Rule) return Precedence;
function Length_of(R: Rule) return Natural;
function First_Rule return Rule;
function Last_Rule return Rule;
function Number_of_Rules return Natural;
procedure Set_Rule_Precedence (R: in Rule; Prec: in Precedence);
procedure Set_Null_Pos (R: in Rule; Position: in Natural);
procedure Handle_Nested_Rule (Current_Rule : in out Rule);
--RJS pragma inline(get_lhs, get_null_pos, get_rule_precedence, length_of);
--& pragma inline(first_rule, last_rule);
end Rule_Table;
-- 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 : rule_table_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:34:28
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxrule_table_body.ada
-- $Header: rule_table_body.a,v 0.1 86/04/01 15:11:44 ada Exp $
-- $Log: rule_table_body.a,v $
-- Revision 0.1 86/04/01 15:11:44 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:41:08 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.
--
package body Rule_Table is
SCCS_ID : constant String := "@(#) rule_table_body.ada, Version 1.2";
Rcs_ID : constant String := "$Header: rule_table_body.a,v 0.1 86/04/01 15:11:44 ada Exp $";
-- Rules are implemented as an array of linked lists
Number_of_Nested_Rules : Integer := 0;
type RHS_Element;
type RHS_Pointer is access RHS_Element;
type RHS_Element is
record
RHS_Symbol: Grammar_Symbol;
Next : RHS_Pointer;
end record;
type Rule_Entry is
record
LHS_Symbol : Grammar_Symbol;
RHS : RHS_Pointer;
Length : Natural;
Null_Pos : Natural;
Prec : Precedence;
end record;
Rule_List: array(Rule) of Rule_Entry;
Next_Free_Rule: Rule := 0;
function Get_Rule_Precedence(R : Rule) return Precedence is
begin
return Rule_List(R).Prec;
end Get_Rule_Precedence;
function Make_Rule(LHS: Grammar_Symbol) return Rule is
R : Rule := Next_Free_Rule;
begin
Rule_List(R) :=
(LHS, RHS => null, Length => 0, Null_Pos => 0, Prec => 0);
Next_Free_Rule := Next_Free_Rule + 1;
return R;
end Make_Rule;
procedure Append_RHS(R: in Rule; RHS: in Grammar_Symbol) is
Temp_Pointer: RHS_Pointer;
begin
if Is_Terminal(RHS) then
Rule_List(R).Prec := Get_Precedence(RHS);
end if;
if Rule_List(R).RHS = null then
Rule_List(R).RHS := new RHS_Element'(RHS, null);
else
Temp_Pointer := Rule_List(R).RHS;
while Temp_Pointer.Next /= null loop
Temp_Pointer := Temp_Pointer.Next;
end loop;
Temp_Pointer.Next := new RHS_Element'(RHS, null);
end if;
Rule_List(R).Length := Rule_List(R).Length + 1;
end Append_RHS;
function Get_LHS(R: Rule) return Grammar_Symbol is
begin
return Rule_List(R).LHS_Symbol;
end Get_LHS;
function Get_Null_Pos(R: Rule) return Natural is
begin
return Rule_List(R).Null_Pos;
end Get_Null_Pos;
procedure Set_Null_Pos(R : in Rule; Position: in Natural) is
begin
Rule_List(R).Null_Pos := Position;
end Set_Null_Pos;
function Get_RHS(R: Rule; Position: Positive) return Grammar_Symbol is
Temp_Pointer: RHS_Pointer;
begin
Temp_Pointer := Rule_List(R).RHS;
for I in 2..Position loop
Temp_Pointer := Temp_Pointer.Next;
end loop;
return Temp_Pointer.RHS_Symbol;
end Get_RHS;
function Length_of(R: Rule) return Natural is
begin
return Rule_List(R).Length;
end Length_of;
function First_Rule return Rule is
begin
return 0;
end First_Rule;
function Last_Rule return Rule is
begin
return Next_Free_Rule - 1;
end Last_Rule;
function Number_of_Rules return Natural is
begin
return Natural(Next_Free_Rule) - 1;
end Number_of_Rules;
procedure Handle_Nested_Rule(Current_Rule : in out Rule) is
Temp : Rule_Entry;
LHS : Grammar_Symbol;
New_Rule : Rule;
begin
-- Make a new rule prefixed by $$N
Number_of_Nested_Rules := Number_of_Nested_Rules + 1;
LHS := Insert_Identifier("$$" & Integer'Image(Number_of_Nested_Rules));
New_Rule := Make_Rule(LHS);
Append_RHS(Current_Rule,LHS);
-- Exchange the rule positions of the new rule and the current rule
-- by swapping contents and exchanging the rule positions
Temp := Rule_List(Current_Rule);
Rule_List(Current_Rule) := Rule_List(New_Rule);
Rule_List(New_Rule) := Temp;
Current_Rule := New_Rule;
end Handle_Nested_Rule;
procedure Set_Rule_Precedence(R: in Rule; Prec: in Precedence) is
begin
Rule_List(R).Prec := Prec;
end Set_Rule_Precedence;
end Rule_Table;
-- 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 : set_pack.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:34:47
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxset_pack.ada
-- $Header: set_pack.a,v 0.1 86/04/01 15:11:51 ada Exp $
-- $Log: set_pack.a,v $
-- Revision 0.1 86/04/01 15:11:51 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:41:22 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.
--
-- Uses the predefined equality operator "=" on variables of type Universe
generic
type Universe is private;
with function "<" (Element_1, Element_2: Universe) return Boolean;
package Set_Pack is
type Set is limited private;
procedure Make_Null (Set_1: in out Set);
procedure Insert (Element : in Universe; Into : in out Set);
procedure Insert (Set_1 : in Set; Into : in out Set);
procedure Delete (Element : in Universe; From : in out Set);
procedure Assign (Object : in out Set; Value : in Set);
-- Nulls value !
procedure Fassign(Object : in out Set; Value : in out Set);
function Is_Member (Element: Universe; Of_Set: Set) return Boolean;
function Is_Empty (Set_1: Set) return Boolean;
function Size_of (Set_1: Set) return Natural;
function "=" (Set_1 : Set; Set_2 : Set) return Boolean;
type Set_Iterator is limited private;
procedure Initialize (Iterator : in out Set_Iterator; Using : in Set);
function More (Iterator: Set_Iterator) return Boolean;
procedure Next (Iterator: in out Set_Iterator; Element: out Universe);
No_More_Elements : exception;
-- raised if you call NEXT when MORE is false.
--RJS
pragma inline(is_empty, size_of, more, next);
private
type Cell;
type Link is access Cell;
type Set is
record
Size : Natural;
Head : Link := null;
end record;
type Set_Iterator is new Link;
end Set_Pack;
-- 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 : set_pack_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:35:14
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxset_pack_body.ada
-- $Header: set_pack_body.a,v 0.1 86/04/01 15:11:59 ada Exp $
-- $Log: set_pack_body.a,v $
-- Revision 0.1 86/04/01 15:11:59 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:41:30 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.
--
package body Set_Pack is
SCCS_ID : constant String := "@(#) set_pack_body.ada, Version 1.2";
Rcs_ID : constant String := "$Header: set_pack_body.a,v 0.1 86/04/01 15:11:59 ada Exp $";
type Cell is
record
Value : Universe;
Next : Link;
end record;
Extras : Link; -- For garbage collection.
function Get_Node return Link;
--RJS pragma inline(get_node);
function Get_Node return Link is
Temp_Link : Link;
begin
if Extras = null then
return new Cell;
else
Temp_Link := Extras;
Extras := Extras.Next;
Temp_Link.Next := null;
return Temp_Link;
end if;
end Get_Node;
procedure Make_Null (Set_1: in out Set) is
Temp_Link : Link;
begin
if Set_1.Head = null then
Set_1.Size := 0;
return;
end if;
-- Find tail of set_1 --
Temp_Link := Set_1.Head;
while Temp_Link.Next /= null loop
Temp_Link := Temp_Link.Next;
end loop;
-- Add set_1 elements to the extras stack --
Temp_Link.Next := Extras;
Extras := Set_1.Head;
Set_1 := (Size => 0, Head => null);
end Make_Null;
procedure Assign (Object : in out Set; Value : in Set) is
Temp_1, Temp_2: Link;
begin
if Object = Value then
return;
else
Make_Null(Object);
end if;
if Value.Head = null then
return;
end if;
Object.Head := Get_Node;
Object.Head.Value := Value.Head.Value;
Object.Head.Next := null;
Temp_1 := Object.Head;
Temp_2 := Value.Head.Next;
while Temp_2 /= null loop
Temp_1.Next := Get_Node;
Temp_1.Next.all := (Value => Temp_2.Value, Next => null);
Temp_1 := Temp_1.Next;
Temp_2 := Temp_2.Next;
end loop;
Temp_1.Next := null;
Object.Size := Value.Size;
end Assign;
procedure Insert (Element : in Universe; Into : in out Set) is
Temp_Link : Link;
Temp_Link_2 : Link;
begin
if Into.Head = null or else Element < Into.Head.Value then
Temp_Link := Get_Node;
Temp_Link.all := (Value => Element, Next => Into.Head);
Into.Head := Temp_Link;
Into.Size := Into.Size + 1;
return;
end if;
if Into.Head.Value = Element then
return;
end if;
Temp_Link := Into.Head;
while Temp_Link.Next /= null loop
if Element = Temp_Link.Next.Value then -- Already in the list.
return;
elsif Element < Temp_Link.Next.Value then
exit; -- Found place to insert.
else
Temp_Link := Temp_Link.Next;
end if;
end loop;
-- insert element --
Temp_Link_2 := Get_Node;
Temp_Link_2.Next := Temp_Link.Next;
Temp_Link_2.Value := Element;
Temp_Link.Next := Temp_Link_2;
Into.Size := Into.Size + 1;
end Insert;
procedure Insert (Set_1 : in Set; Into : in out Set) is
Temp, Trav1, Trav2 : Link;
begin
if Set_1.Head = null then
return;
elsif Set_1.Head = Into.Head then
return;
elsif Into.Head = null then
Assign(Into, Set_1);
return;
end if;
if Set_1.Head.Value < Into.Head.Value then
Temp := Into.Head;
Into.Head := Get_Node;
Into.Head.all := (Set_1.Head.Value, Temp);
Trav1 := Set_1.Head.Next;
Into.Size := Into.Size + 1;
elsif Set_1.Head.Value = Into.Head.Value then
Trav1 := Set_1.Head.Next;
else
Trav1 := Set_1.Head;
end if;
Trav2 := Into.Head;
while Trav1 /= null loop
while Trav2.Next /= null and then
Trav2.Next.Value < Trav1.Value loop
Trav2 := Trav2.Next;
end loop;
if Trav2.Next = null then
while Trav1 /= null loop
Trav2.Next := Get_Node;
Trav2.Next.all := (Trav1.Value, null);
Trav1 := Trav1.Next;
Trav2 := Trav2.Next;
Into.Size := Into.Size + 1;
end loop;
return;
end if;
if Trav2.Next.Value /= Trav1.Value then
Temp := Trav2.Next;
Trav2.Next := Get_Node;
Trav2.Next.all := (Trav1.Value, Temp);
Trav2 := Trav2.Next;
Into.Size := Into.Size + 1;
end if;
Trav1 := Trav1.Next;
end loop;
end Insert;
procedure Delete (Element : in Universe; From : in out Set) is
Temp_Link : Link;
T : Link;
begin
if From.Head = null then
return;
elsif Element < From.Head.Value then
return;
elsif Element = From.Head.Value then
Temp_Link := From.Head;
From.Head := From.Head.Next;
From.Size := From.Size - 1;
Temp_Link.Next := Extras;
Extras := Temp_Link;
return;
end if;
Temp_Link := From.Head;
while Temp_Link.Next /= null and then
Temp_Link.Next.Value < Element
loop
Temp_Link := Temp_Link.Next;
end loop;
if Temp_Link.Next /= null and then
Temp_Link.Next.Value = Element
then
T := Temp_Link.Next;
Temp_Link.Next := Temp_Link.Next.Next;
T.Next := Extras;
Extras := T;
From.Size := From.Size - 1;
end if;
end Delete;
procedure Fassign (Object : in out Set; Value : in out Set) is
begin
-- Free the contents of OBJECT first.
Object := Value;
Value := (Head => null, Size => 0);
end Fassign;
function Is_Member (Element: Universe; Of_Set: Set) return Boolean is
Temp_Link : Link;
begin
Temp_Link := Of_Set.Head;
while Temp_Link /= null and then Temp_Link.Value < Element loop
Temp_Link := Temp_Link.Next;
end loop;
return Temp_Link /= null and then Temp_Link.Value = Element;
end Is_Member;
function Is_Empty (Set_1: Set) return Boolean is
begin
return Set_1.Head = null;
end Is_Empty;
function Size_of (Set_1: Set) return Natural is
begin
return Set_1.Size;
end Size_of;
function "=" (Set_1 : Set; Set_2 : Set) return Boolean is
Link_1, Link_2: Link;
begin
if Set_1.Size /= Set_2.Size then
return False;
end if;
Link_1 := Set_1.Head;
Link_2 := Set_2.Head;
while Link_1 /= null and then Link_2 /= null loop
if Link_1.Value /= Link_2.Value then
exit;
end if;
Link_1 := Link_1.Next;
Link_2 := Link_2.Next;
end loop;
return Link_1 = Link_2; -- True if both equal to null
end "=";
procedure Initialize (Iterator : in out Set_Iterator; Using : in Set) is
begin
Iterator := Set_Iterator(Using.Head);
end Initialize;
function More (Iterator: Set_Iterator) return Boolean is
begin
return Iterator /= null;
end More;
procedure Next (Iterator: in out Set_Iterator; Element: out Universe) is
begin
Element := Iterator.Value;
Iterator := Set_Iterator(Iterator.Next);
exception
when Constraint_Error =>
raise No_More_Elements;
end Next;
end Set_Pack;
-- 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 : shift_reduce_file.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:35:35
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxshift_reduce_file.ada
-- $Header: shift_reduce_file.a,v 0.1 86/04/01 15:12:13 ada Exp $
-- $Log: shift_reduce_file.a,v $
-- Revision 0.1 86/04/01 15:12:13 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:41:42 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.
--
package Shift_Reduce_File is
procedure Open_Write;
procedure Write(S: in String);
procedure Write_Line(S: in String);
procedure Write(C: in Character);
procedure Close_Write;
end Shift_Reduce_File;
with Text_IO, File_Names;
use Text_IO, File_Names;
package body Shift_Reduce_File is
SCCS_ID : constant String := "@(#) shift_reduce_file.ada, Version 1.2";
Rcs_ID : constant String := "$Header: shift_reduce_file.a,v 0.1 86/04/01 15:12:13 ada Exp $";
The_File : File_Type;
procedure Open_Write is
begin
Create(The_File, Out_File, Get_Shift_Reduce_File_Name);
Write_Line("package " & Shift_Reduce_Tables_Unit_Name & " is");
Write_Line("");
Write_Line(" type Small_Integer is range -32_000 .. 32_000;");
Write_Line("");
Write_Line(" type Shift_Reduce_Entry is record");
Write_Line(" T : Small_Integer;");
Write_Line(" Act : Small_Integer;");
Write_Line(" end record;");
Write_Line(" pragma Pack(Shift_Reduce_Entry);");
Write_Line("");
Write_Line(" subtype Row is Integer range -1 .. Integer'Last;");
Write_Line("");
Write_Line(" --pragma suppress(index_check);");
Write_Line("");
Write_Line(" type Shift_Reduce_Array is array " &
"(Row range <>) of Shift_Reduce_Entry;");
Write_Line("");
Write_Line(" Shift_Reduce_Matrix : constant Shift_Reduce_Array :=");
Write_Line(" ( (-1,-1) -- Dummy Entry");
New_Line(The_File);
end Open_Write;
procedure Close_Read is
begin
Delete(The_File);
end Close_Read;
procedure Close_Write is
begin
Write_Line("end " & Shift_Reduce_Tables_Unit_Name & ";");
Close(The_File);
end Close_Write;
procedure Write(S: in String) is
begin
Put(The_File, S) ;
end;
procedure Write_Line(S: in String) is
begin
Put_Line(The_File, S);
end Write_Line;
procedure Write(C: in Character) is
begin
Put(The_File,C);
end;
end Shift_Reduce_File;
-- 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 : source_file.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:35:54
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxsource_file.ada
-- $Header: source_file.a,v 0.1 86/04/01 15:12:23 ada Exp $
-- $Log: source_file.a,v $
-- Revision 0.1 86/04/01 15:12:23 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:41:53 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.
--
package Source_File is
--. This package provides input from the source file to the lexical
--. analyzer.
--. UNGET will work to unget up to one character. You can unget more
--. characters until you try to unget an EOLN where the exception
--. PUSHBACK_ERROR is raised.
--. The next character in the input stream
--. can be looked at using PEEK_NEXT_CHAR without affecting the input
--. stream.
procedure Open;
procedure Close;
procedure Get_Char (Ch: out Character);
procedure Unget_Char (Ch: in Character);
function Peek_Next_Char return Character;
function Is_End_of_File return Boolean;
function Source_Line_Number return Natural;
--RJS: Added to make internal Ayacc buffers consistent with
-- source line length. ----v
function Maximum_Line_Length return Natural;
Eof : constant Character := Ascii.Nul;
Eoln : constant Character := Ascii.Lf;
procedure Print_Context_Lines;
--. Prints the previous line followed by the current line
--. followed by a pointer to the position of the source file.
--. Intended for printing error messages.
procedure Read_Line(Source_Line: out String; Last: out Natural);
--. Used to dump the contents of the
--. source file one line at a time. It is intended to be be used
--. to dump the Ada section code (after the third %%) of the
--. source file.
Pushback_Error : exception;
end Source_File;
-- 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 : source_file_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:36:09
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxsource_file_body.ada
-- $Header: source_file_body.a,v 0.1 86/04/01 15:12:32 ada Exp $
-- $Log: source_file_body.a,v $
-- Revision 0.1 86/04/01 15:12:32 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:42:02 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 Text_IO, File_Names;
use Text_IO;
package body Source_File is
SCCS_ID : constant String := "@(#) source_file_body.ada, Version 1.2";
Rcs_ID : constant String := "$Header: source_file_body.a,v 0.1 86/04/01 15:12:32 ada Exp $";
Input_File : File_Type;
Max_Line_Length : constant := 260;
type Long_STR is
record
Name : String(1..Max_Line_Length);
Length : Natural := 0;
end record;
Current_Line : Long_STR;
Previous_Line : Long_STR;
Column_Number : Natural; -- column number of current_line.
Line_Number : Natural;
Get_New_Line : Boolean := True;
End_of_Source_File : Boolean := False;
procedure Open is
use File_Names;
begin
Open(Input_File, In_File, Get_Source_File_Name);
Current_Line := ((others => ' '), 0);
Previous_Line := ((others => ' '), 0);
Column_Number := 1;
Line_Number := 0;
exception
when Name_Error | Use_Error =>
Put_Line("Ayacc: Error Opening """ & Get_Source_File_Name & """.");
raise;
end Open;
procedure Close is
begin
Close(Input_File);
end Close;
function Is_End_of_File return Boolean is
begin
return End_of_File(Input_File);
end Is_End_of_File;
function Source_Line_Number return Natural is
begin
return Line_Number;
end Source_Line_Number;
function Maximum_Line_Length return Natural is
begin
return Max_Line_Length;
end Maximum_Line_Length;
procedure Get_Char(Ch: out Character) is
begin
if Get_New_Line then
Previous_Line := Current_Line;
Get_Line(Input_File, Current_Line.Name, Current_Line.Length);
Get_New_Line := False;
Column_Number := 1;
Line_Number := Line_Number + 1;
end if;
if Column_Number > Current_Line.Length then
if End_of_File(Input_File) then
Ch := Eof;
End_of_Source_File := True;
return;
end if;
Ch := Eoln;
Get_New_Line := True;
else
Ch := Current_Line.Name(Column_Number);
Column_Number := Column_Number + 1;
end if;
end Get_Char;
-- Note: You can't correctly peek at next character if the last character
-- read is a EOLN. It is assumed that the lexical analyzer won't
-- call this function in that case.
function Peek_Next_Char return Character is
begin
if Column_Number > Current_Line.Length then
if End_of_File(Input_File) then
return Eof;
else
return Eoln;
end if;
end if;
return Current_Line.Name(Column_Number);
end Peek_Next_Char;
procedure Unget_Char(Ch : in Character) is
begin
if Get_New_Line then
Get_New_Line := False;
elsif End_of_Source_File then
End_of_Source_File := False;
elsif Column_Number = 1 then
Put_Line("Ayacc: Error in Unget_Char, Attempt to 'unget' an EOLN");
raise Pushback_Error;
else
Column_Number := Column_Number - 1;
end if;
end Unget_Char;
procedure Print_Context_Lines is
Ptr_Location : Integer := 0;
begin
-- Print previous line followed by current line --
Put(Integer'Image(Line_Number-1) & Ascii.Ht);
Put_Line(Previous_Line.Name(1..Previous_Line.Length));
Put(Integer'Image(Line_Number) & Ascii.Ht);
Put_Line(Current_Line.Name(1..Current_Line.Length));
-- Correct for any tab characters so that the pointer will
-- point to the proper location on the source line.
for I in 1..Column_Number - 1 loop
if Current_Line.Name(I) = Ascii.Ht then -- Adjust for tab.
Ptr_Location := (((Ptr_Location / 8) + 1) * 8);
else
Ptr_Location := Ptr_Location + 1;
end if;
end loop;
Put(Ascii.Ht);
for I in 1..Ptr_Location - 1 loop
Put('-');
end loop;
Put('^');
end Print_Context_Lines;
procedure Read_Line(Source_Line: out String; Last: out Natural) is
begin
Get_Line(Input_File, Source_Line, Last);
Line_Number := Line_Number + 1;
end Read_Line;
end Source_File;
-- 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 : stack.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:36:24
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxstack.ada
-- $Header: stack.a,v 0.1 86/04/01 15:12:46 ada Exp $
-- $Log: stack.a,v $
-- Revision 0.1 86/04/01 15:12:46 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:42:12 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.
--
-- --
-- Authors : David Taback , Deepak Tolani --
-- Copyright : 1987, University of California Irvine --
-- --
-- If you --
-- modify the source code or if you have any suggestions or questions --
-- regarding ayacc, we would like to hear from you. Our mailing --
-- addresses are : --
-- taback@icsc.uci.edu --
-- tolani@icsc.uci.edu --
-- --
generic
type Element is private;
package Stack_Pack is
type Stack is limited private;
Stack_Underflow : exception;
function Top_Value (S: in Stack) return Element;
function Depth_of_Stack (S: in Stack) return Natural;
procedure Make_Stack(S: out Stack);
procedure Push(S: in out Stack; Value: in Element);
procedure Pop (S: in out Stack; Value: out Element);
procedure Free_Stack(S: in out Stack);
private
type Node;
type Link is access Node;
pragma Controlled(Link);
type Stack is
record
Tos : Natural;
Top : Link;
Extras : Link;
end record;
end Stack_Pack;
with Unchecked_Deallocation;
package body Stack_Pack is
SCCS_ID : constant String := "@(#) stack.ada, Version 1.2";
type Node is
record
Datum : Element;
Next : Link;
end record;
function Top_Value (S: in Stack) return Element is
begin
if S.Top = null then
raise Stack_Underflow;
else
return S.Top.Datum;
end if;
end Top_Value;
function Depth_of_Stack (S: in Stack) return Natural is
begin
return S.Tos;
end Depth_of_Stack;
procedure Make_Stack(S: out Stack) is
begin
S := (Tos => 0, Top | Extras => null);
end Make_Stack;
procedure Push(S: in out Stack; Value: in Element) is
New_Node : Link;
begin
S.Tos := S.Tos + 1;
if S.Extras = null then
New_Node := new Node;
else
New_Node := S.Extras;
S.Extras := S.Extras.Next;
end if;
New_Node.all := (Datum => Value, Next => S.Top);
S.Top := New_Node;
end Push;
procedure Pop (S: in out Stack; Value: out Element) is
Temp : Link;
begin
if S.Tos = 0 then
raise Stack_Underflow;
end if;
Value := S.Top.Datum;
Temp := S.Top.Next;
S.Top.Next := S.Extras;
S.Extras := S.Top;
S.Top := Temp;
S.Tos := S.Tos - 1;
end Pop;
procedure Free is new Unchecked_Deallocation(Node, Link);
-- procedure free(x : link);
-- pragma interface(c , free);
procedure Free_List(List: in out Link) is
Temp : Link;
begin
Temp := List;
while Temp /= null loop
List := List.Next;
Free(Temp);
Temp := List;
end loop;
end Free_List;
procedure Free_Stack(S: in out Stack) is
begin
Free_List(S.Top);
Free_List(S.Extras);
end Free_Stack;
end Stack_Pack;
-- Module : stack_pkg.ada
-- Component of : common_library
-- Version : 1.2
-- Date : 11/21/86 16:32:31
-- SCCS File : disk21~/rschm/hasee/sccs/common_library/sccs/sxstack_pkg.ada
-- $Source: /nosc/work/abstractions/stack/RCS/stack.bdy,v $
-- $Revision: 1.3 $ -- $Date: 85/02/01 10:19:36 $ -- $Author: ron $
-- $Source: /nosc/work/abstractions/stack/RCS/stack.bdy,v $
-- $Revision: 1.3 $ -- $Date: 85/02/01 10:19:36 $ -- $Author: ron $
with unchecked_deallocation;
package body stack_pkg is
SCCS_ID : constant String := "@(#) stack_pkg.ada, Version 1.2";
--| Overview:
--| Implementation scheme is totally described by the statements of the
--| representation invariants and abstraction function that appears in
--| the package specification. The implementation is so trivial that
--| further documentation is unnecessary.
use elem_list_pkg;
-- Constructors:
function create
return stack is
begin
return new stack_rec'(size => 0, elts => create);
end create;
procedure push(s: in out stack;
e: elem_type) is
begin
s.size := s.size + 1;
s.elts := attach(e, s.elts);
exception
when constraint_error =>
raise uninitialized_stack;
end push;
procedure pop(s: in out stack) is
begin
DeleteHead(s.elts);
s.size := s.size - 1;
exception
when EmptyList =>
raise empty_stack;
when constraint_error =>
raise uninitialized_stack;
end pop;
procedure pop(s: in out stack;
e: out elem_type) is
begin
e := FirstValue(s.elts);
DeleteHead(s.elts);
s.size := s.size - 1;
exception
when EmptyList =>
raise empty_stack;
when constraint_error =>
raise uninitialized_stack;
end pop;
function copy(s: stack)
return stack is
begin
if s = null then raise uninitialized_stack; end if;
return new stack_rec'(size => s.size,
elts => copy(s.elts));
end;
-- Queries:
function top(s: stack)
return elem_type is
begin
return FirstValue(s.elts);
exception
when EmptyList =>
raise empty_stack;
when constraint_error =>
raise uninitialized_stack;
end top;
function size(s: stack)
return natural is
begin
return s.size;
exception
when constraint_error =>
raise uninitialized_stack;
end size;
function is_empty(s: stack)
return boolean is
begin
return s.size = 0;
exception
when constraint_error =>
raise uninitialized_stack;
end is_empty;
-- Heap Management:
procedure destroy(s: in out stack) is
procedure free_stack is
new unchecked_deallocation(stack_rec, stack);
begin
destroy(s.elts);
free_stack(s);
exception
when constraint_error => -- stack is null
return;
end destroy;
end stack_pkg;
-- Module : stack_pkg_.ada
-- Component of : common_library
-- Version : 1.2
-- Date : 11/21/86 16:33:02
-- SCCS File : disk21~/rschm/hasee/sccs/common_library/sccs/sxstack_pkg_.ada
-- $Source: /nosc/work/abstractions/stack/RCS/stack.spc,v $
-- $Revision: 1.5 $ -- $Date: 85/02/01 09:57:17 $ -- $Author: ron $
-- $Source: /nosc/work/abstractions/stack/RCS/stack.spc,v $
-- $Revision: 1.5 $ -- $Date: 85/02/01 09:57:17 $ -- $Author: ron $
with lists; --| Implementation uses lists. (private)
generic
type elem_type is private; --| Component element type.
package stack_pkg is
--| Overview:
--| This package provides the stack abstract data type. Element type is
--| a generic formal parameter to the package. There are no explicit
--| bounds on the number of objects that can be pushed onto a given stack.
--| All standard stack operations are provided.
--|
--| The following is a complete list of operations, written in the order
--| in which they appear in the spec. Overloaded subprograms are followed
--| by (n), where n is the number of subprograms of that name.
--|
--| Constructors:
--| create
--| push
--| pop (2)
--| copy
--| Query Operations:
--| top
--| size
--| is_empty
--| Heap Management:
--| destroy
--| Notes:
--| Programmer: Ron Kownacki
type stack is private; --| The stack abstract data type.
-- Exceptions:
uninitialized_stack: exception;
--| Raised on attempt to manipulate an uninitialized stack object.
--| The initialization operations are create and copy.
empty_stack: exception;
--| Raised by some operations when empty.
-- Constructors:
function create
return stack;
--| Effects:
--| Return the empty stack.
procedure push(s: in out stack;
e: elem_type);
--| Raises: uninitialized_stack
--| Effects:
--| Push e onto the top of s.
--| Raises uninitialized_stack iff s has not been initialized.
procedure pop(s: in out stack);
--| Raises: empty_stack, uninitialized_stack
--| Effects:
--| Pops the top element from s, and throws it away.
--| Raises empty_stack iff s is empty.
--| Raises uninitialized_stack iff s has not been initialized.
procedure pop(s: in out stack;
e: out elem_type);
--| Raises: empty_stack, uninitialized_stack
--| Effects:
--| Pops the top element from s, returns it as the e parameter.
--| Raises empty_stack iff s is empty.
--| Raises uninitialized_stack iff s has not been initialized.
function copy(s: stack)
return stack;
--| Raises: uninitialized_stack
--| Return a copy of s.
--| Stack assignment and passing stacks as subprogram parameters
--| result in the sharing of a single stack value by two stack
--| objects; changes to one will be visible through the others.
--| copy can be used to prevent this sharing.
--| Raises uninitialized_stack iff s has not been initialized.
-- Queries:
function top(s: stack)
return elem_type;
--| Raises: empty_stack, uninitialized_stack
--| Effects:
--| Return the element on the top of s. Raises empty_stack iff s is
--| empty.
--| Raises uninitialized_stack iff s has not been initialized.
function size(s: stack)
return natural;
--| Raises: uninitialized_stack
--| Effects:
--| Return the current number of elements in s.
--| Raises uninitialized_stack iff s has not been initialized.
function is_empty(s: stack)
return boolean;
--| Raises: uninitialized_stack
--| Effects:
--| Return true iff s is empty.
--| Raises uninitialized_stack iff s has not been initialized.
-- Heap Management:
procedure destroy(s: in out stack);
--| Effects:
--| Return the space consumed by s to the heap. No effect if s is
--| uninitialized. In any case, leaves s in uninitialized state.
private
package elem_list_pkg is new lists(elem_type);
subtype elem_list is elem_list_pkg.list;
type stack_rec is
record
size: natural := 0;
elts: elem_list := elem_list_pkg.create;
end record;
type stack is access stack_rec;
--| Let an instance of the representation type, r, be denoted by the
--| pair, <size, elts>. Dot selection is used to refer to these
--| components.
--|
--| Representation Invariants:
--| r /= null
--| elem_list_pkg.length(r.elts) = r.size.
--|
--| Abstraction Function:
--| A(<size, elem_list_pkg.create>) = stack_pkg.create.
--| A(<size, elem_list_pkg.attach(e, l)>) = push(A(<size, l>), e).
end stack_pkg;
-- 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 : str_pack.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:36:46
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxstr_pack.ada
-- $Header: str_pack.a,v 0.1 86/04/01 15:13:01 ada Exp $
-- $Log: str_pack.a,v $
-- Revision 0.1 86/04/01 15:13:01 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:42:23 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.
--
package STR_Pack is
-- This package contains the type declarations and procedures
-- for the minimal string minipulation needed by ayacc.
Maximum : constant := 1024; --RJS 120;
subtype Index is Integer range 0 .. Maximum;
type STR(Maximum_Length : Index) is limited private;
function Length_of (S: STR) return Integer;
function Value_of (S: STR) return String;
function Is_Empty (S: STR) return Boolean;
procedure Assign (Value: in STR; To: in out STR);
procedure Assign (Value: in String; To: in out STR);
procedure Assign (Value: in Character; To: in out STR);
procedure Append (Tail: in Character; To: in out STR);
procedure Append (Tail: in String; To: in out STR);
procedure Append (Tail: in STR; To: in out STR);
procedure Upper_Case(S: in out STR);
procedure Lower_Case(S: in out STR);
function Upper_Case (S : in STR) return STR;
function Lower_Case (S : in STR) return STR;
--RJS
pragma inline (length_of, --RJS value_of,
is_empty,
append);
private
type STR(Maximum_Length : Index) is
record
Name : String(1..Maximum_Length);
Length : Index := 0;
end record;
end STR_Pack;
package body STR_Pack is
SCCS_ID : constant String := "@(#) str_pack.ada, Version 1.2";
Rcs_ID : constant String := "$Header: str_pack.a,v 0.1 86/04/01 15:13:01 ada Exp $";
function Upper_Case (S : in STR) return STR is
Upper_STR : STR (S.Name'Length) := S;
begin
for I in 1..S.Length loop
if S.Name(I) in 'a'..'z' then
Upper_STR.Name(I) := Character'Val(Character'Pos(S.Name(I)) -
Character'Pos('a') + Character'Pos('A'));
end if;
end loop;
return Upper_STR;
end Upper_Case;
function Lower_Case (S : in STR) return STR is
Lower_STR : STR (S.Name'Length) := S;
begin
for I in 1..S.Length loop
if S.Name(I) in 'A'..'Z' then
Lower_STR.Name(I) := Character'Val(Character'Pos(S.Name(I)) -
Character'Pos('A') + Character'Pos('a'));
end if;
end loop;
return Lower_STR;
end Lower_Case;
procedure Upper_Case(S: in out STR) is
begin
S := Upper_Case (S);
end Upper_Case;
procedure Lower_Case(S: in out STR) is
begin
S := Lower_Case (S);
end Lower_Case;
procedure Assign (Value: in STR; To: in out STR) is
begin
To := Value;
end Assign;
procedure Assign (Value: in String; To: in out STR) is
begin
To.Name(1..Value'Length) := Value;
To.Length := Value'Length;
end Assign;
procedure Assign (Value: in Character; To: in out STR) is
begin
To.Name(1) := Value;
To.Length := 1;
end Assign;
procedure Append (Tail: in STR; To: in out STR) is
F, L : Natural;
begin
F := To.Length + 1;
L := F + Tail.Length - 1;
To.Name(F..L) := Tail.Name(1..Tail.Length);
To.Length := L;
end Append;
procedure Append (Tail: in String; To: in out STR) is
F, L: Natural;
begin
F := To.Length + 1;
L := F + Tail'Length - 1;
To.Name(F .. L) := Tail;
To.Length := L;
end Append;
procedure Append (Tail: in Character; To: in out STR) is
begin
To.Length := To.Length + 1;
To.Name(To.Length) := Tail;
end Append;
function Length_of(S: STR) return Integer is
begin
return S.Length;
end Length_of;
function Value_of(S: STR) return String is
begin
return S.Name(1..S.Length);
end Value_of;
function Is_Empty(S: STR) return Boolean is
begin
return S.Length = 0;
end Is_Empty;
end STR_Pack;
-- 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 : str_pack.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:36:46
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxstr_pack.ada
-- $Header: str_pack.a,v 0.1 86/04/01 15:13:01 ada Exp $
-- $Log: str_pack.a,v $
-- Revision 0.1 86/04/01 15:13:01 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:42:23 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.
--
package STR_Pack is
-- This package contains the type declarations and procedures
-- for the minimal string minipulation needed by ayacc.
-- COMPILER BUG :
-- maximun discriminat value. note that the discriminant is ignored
-- in this implementation to work around a bug in VADS 5.41
Maximum : constant := 1024; --RJS 120;
-- COMPILER BUG :
-- estimated 'safe' constant. note that a constraint error may
-- result if a string length exceeds this limit. in particular,
-- command line strings in package command_line_interface.a have
-- a maximum length of 1024. WATCH OUT. it is ASSUMED that
-- no command lines will exceed 512.
Vads_5_41_Maximum : constant := 512;
subtype Index is Integer range 0 .. Maximum;
type STR(Maximum_Length : Index) is limited private;
function Length_of (S: STR) return Integer;
function Value_of (S: STR) return String;
function Is_Empty (S: STR) return Boolean;
procedure Assign (Value: in STR; To: in out STR);
procedure Assign (Value: in String; To: in out STR);
procedure Assign (Value: in Character; To: in out STR);
procedure Append (Tail: in Character; To: in out STR);
procedure Append (Tail: in String; To: in out STR);
procedure Append (Tail: in STR; To: in out STR);
procedure Upper_Case(S: in out STR);
procedure Lower_Case(S: in out STR);
function Upper_Case (S : in STR) return STR;
function Lower_Case (S : in STR) return STR;
--RJS
pragma inline (length_of, --RJS value_of,
is_empty,
append);
private
type STR(Maximum_Length : Index) is
record
-- COMPILER BUG :
-- must make upper bound of string independent
-- of discriminant due to a compiler error in
-- VADS 5.41
--Name : String(1..Maximum_Length);
Name : String(1..Vads_5_41_Maximum);
Length : Index := 0;
end record;
end STR_Pack;
package body STR_Pack is
SCCS_ID : constant String := "@(#) str_pack.ada, Version 1.2";
Rcs_ID : constant String := "$Header: str_pack.a,v 0.1 86/04/01 15:13:01 ada Exp $";
function Upper_Case (S : in STR) return STR is
-- COMPILER BUG :
-- the discriminant and the string length may not
-- correspond
--Upper_STR : STR (S.Name'Length) := S;
Upper_STR : STR (S.Maximum_Length) := S;
begin
for I in 1..S.Length loop
if S.Name(I) in 'a'..'z' then
Upper_STR.Name(I) := Character'Val(Character'Pos(S.Name(I)) -
Character'Pos('a') + Character'Pos('A'));
end if;
end loop;
return Upper_STR;
end Upper_Case;
function Lower_Case (S : in STR) return STR is
-- COMPILER BUG :
-- the discriminant and the string length may not
-- correspond
--Lower_STR : STR (S.Name'Length) := S;
Lower_STR : STR (S.Maximum_Length) := S;
begin
for I in 1..S.Length loop
if S.Name(I) in 'A'..'Z' then
Lower_STR.Name(I) := Character'Val(Character'Pos(S.Name(I)) -
Character'Pos('A') + Character'Pos('a'));
end if;
end loop;
return Lower_STR;
end Lower_Case;
procedure Upper_Case(S: in out STR) is
begin
S := Upper_Case (S);
end Upper_Case;
procedure Lower_Case(S: in out STR) is
begin
S := Lower_Case (S);
end Lower_Case;
procedure Assign (Value: in STR; To: in out STR) is
begin
To := Value;
end Assign;
procedure Assign (Value: in String; To: in out STR) is
begin
To.Name(1..Value'Length) := Value;
To.Length := Value'Length;
end Assign;
procedure Assign (Value: in Character; To: in out STR) is
begin
To.Name(1) := Value;
To.Length := 1;
end Assign;
procedure Append (Tail: in STR; To: in out STR) is
F, L : Natural;
begin
F := To.Length + 1;
L := F + Tail.Length - 1;
To.Name(F..L) := Tail.Name(1..Tail.Length);
To.Length := L;
end Append;
procedure Append (Tail: in String; To: in out STR) is
F, L: Natural;
begin
F := To.Length + 1;
L := F + Tail'Length - 1;
To.Name(F .. L) := Tail;
To.Length := L;
end Append;
procedure Append (Tail: in Character; To: in out STR) is
begin
To.Length := To.Length + 1;
To.Name(To.Length) := Tail;
end Append;
function Length_of(S: STR) return Integer is
begin
return S.Length;
end Length_of;
function Value_of(S: STR) return String is
begin
return S.Name(1..S.Length);
end Value_of;
function Is_Empty(S: STR) return Boolean is
begin
return S.Length = 0;
end Is_Empty;
end STR_Pack;
-- Module : string_lists.ada
-- Component of : common_library
-- Version : 1.2
-- Date : 11/21/86 16:34:39
-- SCCS File : disk21~/rschm/hasee/sccs/common_library/sccs/sxstring_lists.ada
with String_Pkg;
with Lists;
package String_Lists is new Lists(String_Pkg.String_Type, String_Pkg.Equal);
-- Module : string_pkg.ada
-- Component of : common_library
-- Version : 1.2
-- Date : 11/21/86 16:35:20
-- SCCS File : disk21~/rschm/hasee/sccs/common_library/sccs/sxstring_pkg.ada
-- $Source: /nosc/work/abstractions/string/RCS/string.bdy,v $
-- $Revision: 1.3 $ -- $Date: 85/02/01 10:58:51 $ -- $Author: ron $
-- $Source: /nosc/work/abstractions/string/RCS/string.bdy,v $
-- $Revision: 1.3 $ -- $Date: 85/02/01 10:58:51 $ -- $Author: ron $
with unchecked_deallocation;
with lists, stack_pkg;
package body string_pkg is
SCCS_ID : constant String := "@(#) string_pkg.ada, Version 1.2";
--| Overview:
--| The implementation for most operations is fairly straightforward.
--| The interesting aspects involve the allocation and deallocation of
--| heap space. This is done as follows:
--|
--| 1. A stack of accesses to lists of string_type values is set up
--| so that the top of the stack always refers to a list of values
--| that were allocated since the last invocation of mark.
--| The stack is called scopes, referring to the dynamic scopes
--| defined by the invocations of mark and release.
--| There is an implicit invocation of mark when the
--| package body is elaborated; this is implemented with an explicit
--| invocation in the package initialization code.
--|
--| 2. At each invocation of mark, a pointer to an empty list
--| is pushed onto the stack.
--|
--| 3. At each invocation of release, all of the values in the
--| list referred to by the pointer at the top of the stack are
--| returned to the heap. Then the list, and the pointer to it,
--| are returned to the heap. Finally, the stack is popped.
package string_list_pkg is new lists(string_type);
subtype string_list is string_list_pkg.list;
type string_list_ptr is access string_list;
package scope_stack_pkg is new stack_pkg(string_list_ptr);
subtype scope_stack is scope_stack_pkg.stack;
use string_list_pkg;
use scope_stack_pkg;
scopes: scope_stack; -- See package body overview.
-- Utility functions/procedures:
function enter(s: string_type)
return string_type;
--| Raises: illegal_alloc
--| Effects:
--| Stores s, the address of s.all, in current scope list (top(scopes)),
--| and returns s. Useful for functions that create and return new
--| string_type values.
--| Raises illegal_alloc if the scopes stack is empty.
function match_string(s1, s2: string; start: positive := 1)
return natural;
--| Raises: no_match
--| Effects:
--| Returns the minimum index, i, in s1'range such that
--| s1(i..i + s2'length - 1) = s2. Returns 0 if no such index.
--| Requires:
--| s1'first = 1.
-- Constructors:
function Empty_String return String_Type is
begin
return Create ("");
end Empty_String;
function create(s: string)
return string_type is
subtype constr_str is string(1..s'length);
dec_s: constr_str := s;
begin
return enter(new constr_str'(dec_s));
-- DECada bug; above code (and decl of dec_s) replaces the following:
-- return enter(new constr_str'(s));
end create;
function "&"(s1, s2: string_type)
return string_type is
begin
if is_empty(s1) then return enter(make_persistent(s2)); end if;
if is_empty(s2) then return enter(make_persistent(s1)); end if;
return create(s1.all & s2.all);
end "&";
function "&"(s1: string_type; s2: string)
return string_type is
begin
if s1 = null then return create(s2); end if;
return create(s1.all & s2);
end "&";
function "&"(s1: string; s2: string_type)
return string_type is
begin
if s2 = null then return create(s1); end if;
return create(s1 & s2.all);
end "&";
function substr(s: string_type; i: positive; len: natural)
return string_type is
begin
if len = 0 then return null; end if;
return create(s(i..(i + len - 1)));
exception
when constraint_error => -- on array fetch or null deref
raise bounds;
end substr;
function splice(s: string_type; i: positive; len: natural)
return string_type is
begin
if len = 0 then return enter(make_persistent(s)); end if;
if i + len - 1 > length(s) then raise bounds; end if;
return create(s(1..(i - 1)) & s((i + len)..length(s)));
end splice;
function insert(s1, s2: string_type; i: positive)
return string_type is
begin
if i > length(s1) then raise bounds; end if;
if is_empty(s2) then return create(s1.all); end if;
return create(s1(1..(i - 1)) & s2.all & s1(i..s1'last));
end insert;
function insert(s1: string_type; s2: string; i: positive)
return string_type is
begin
if i > length(s1) then raise bounds; end if;
return create(s1(1..(i - 1)) & s2 & s1(i..s1'last));
end insert;
function insert(s1: string; s2: string_type; i: positive)
return string_type is
begin
if not (i in s1'range) then raise bounds; end if;
if s2 = null then return create(s1); end if;
return create(s1(s1'first..(i - 1)) & s2.all & s1(i..s1'last));
end insert;
procedure lc(c: in out character) is
begin
if ('A' <= c) and then (c <= 'Z') then
c := character'val(character'pos(c) - character'pos('A')
+ character'pos('a'));
end if;
end lc;
procedure uc(c: in out character) is
begin
if ('a' <= c) and then (c <= 'z') then
c := character'val(character'pos(c) - character'pos('a')
+ character'pos('A'));
end if;
end uc;
function lower(s: string)
return string_type is
s2: string_type := create(s);
begin
for i in s2'range loop
lc(s2(i));
end loop;
return s2;
end lower;
function lower(s: string_type)
return string_type is
begin
if s = null then return null; end if;
return lower(s.all);
end lower;
function Mixed (S: String) return String_Type is
Mixed_String : String_Type := Create (S);
begin
if Mixed_String'Length /= 0 then
UC (Mixed_String(Mixed_String'First));
for i in Mixed_String'First + 1 .. Mixed_String'Last
loop
if Mixed_String(i-1) = '_' then
UC (Mixed_String(i));
else
LC (Mixed_String(i));
end if;
end loop;
return Mixed_String;
else
return Empty_String;
end if;
end Mixed;
function Mixed (S : String_Type) return String_Type is
begin
if s = null then
return Empty_String;
else
return Mixed (S.all);
end if;
end Mixed;
function upper(s: string)
return string_type is
s2: string_type := create(s);
begin
for i in s2'range loop
uc(s2(i));
end loop;
return s2;
end upper;
function upper(s: string_type)
return string_type is
begin
if s = null then return null; end if;
return upper(s.all);
end upper;
-- Heap Management:
function make_persistent(s: string_type)
return string_type is
subtype constr_str is string(1..length(s));
begin
if s = null or else s.all = "" then return null;
else return new constr_str'(s.all);
end if;
end make_persistent;
function make_persistent(s: string)
return string_type is
subtype constr_str is string(1..s'length);
begin
if s = "" then return null;
else return new constr_str'(s); end if;
end make_persistent;
procedure real_flush is new unchecked_deallocation(string,
string_type);
--| Effect:
--| Return space used by argument to heap. Does nothing if null.
--| Notes:
--| This procedure is actually the body for the flush procedure,
--| but a generic instantiation cannot be used as a body for another
--| procedure. You tell me why.
procedure flush(s: in out string_type) is
begin
if s /= null then real_flush(s); end if;
-- Actually, the if isn't needed; however, DECada compiler chokes
-- on deallocation of null.
end flush;
procedure mark is
begin
push(scopes, new string_list'(create));
end mark;
procedure release is
procedure flush_list_ptr is
new unchecked_deallocation(string_list, string_list_ptr);
iter: string_list_pkg.ListIter;
top_list: string_list_ptr;
s: string_type;
begin
pop(scopes, top_list);
iter := MakeListIter(top_list.all);
while more(iter) loop
next(iter, s);
flush(s); -- real_flush is bad, DECada bug
-- real_flush(s);
end loop;
destroy(top_list.all);
flush_list_ptr(top_list);
exception
when empty_stack =>
raise illegal_dealloc;
end release;
-- Queries:
function is_empty(s: string_type)
return boolean is
begin
return (s = null) or else (s.all = "");
end is_empty;
function length(s: string_type)
return natural is
begin
if s = null then return 0; end if;
return(s.all'length);
end length;
function value(s: string_type)
return string is
subtype null_range is positive range 1..0;
subtype null_string is string(null_range);
begin
if s = null then return null_string'(""); end if;
return s.all;
end value;
function fetch(s: string_type; i: positive)
return character is
begin
if is_empty(s) or else (not (i in s'range)) then raise bounds; end if;
return s(i);
end fetch;
function equal(s1, s2: string_type)
return boolean is
begin
if is_empty(s1) then return is_empty(s2); end if;
return (s2 /= null) and then (s1.all = s2.all);
-- The above code replaces the following. (DECada buggy)
-- return s1.all = s2.all;
-- exception
-- when constraint_error => -- s is null
-- return is_empty(s1) and is_empty(s2);
end equal;
function equal(s1: string_type; s2: string)
return boolean is
begin
if s1 = null then return s2 = ""; end if;
return s1.all = s2;
end equal;
function equal(s1: string; s2: string_type)
return boolean is
begin
if s2 = null then return s1 = ""; end if;
return s1 = s2.all;
end equal;
--|========================================================================
function Equivalent (Left, Right : in String_Type) return Boolean is
begin
return Equal (Upper (Left), Upper (Right));
end Equivalent;
function Equivalent (Left : in String;
Right : in String_Type) return Boolean is
begin
return Equivalent (Create (Left), Right);
end Equivalent;
function Equivalent (Left : in String_Type;
Right : in String) return Boolean is
begin
return Equivalent (Left, Create (Right));
end Equivalent;
--|========================================================================
function "<" (s1: string_type; s2: string_type)
return boolean is
begin
if is_empty(s1) then
return (not is_empty(s2));
else
return (s1.all < s2);
end if;
-- Got rid of the following code: (Think that DECada is buggy)
--return s1.all < s2.all;
--exception
--when constraint_error => -- on null deref
--return (not is_empty(s2));
-- one of them must be empty
end "<";
function "<"(s1: string_type; s2: string)
return boolean is
begin
if s1 = null then return s2 /= ""; end if;
return s1.all < s2;
end "<";
function "<"(s1: string; s2: string_type)
return boolean is
begin
if s2 = null then return false; end if;
return s1 < s2.all;
end "<";
function "<="(s1: string_type; s2: string_type)
return boolean is
begin
if is_empty(s1) then return true; end if;
return (s1.all <= s2);
-- Replaces the following: (I think DECada is buggy)
--return s1.all <= s2.all;
--exception
--when constraint_error => -- on null deref
--return is_empty(s1); -- one must be empty, so s1<=s2 iff s1 = ""
end "<=";
function "<="(s1: string_type; s2: string)
return boolean is
begin
if s1 = null then return true; end if;
return s1.all <= s2;
end "<=";
function "<="(s1: string; s2: string_type)
return boolean is
begin
if s2 = null then return s1 = ""; end if;
return s1 <= s2.all;
end "<=";
function match_c(s: string_type; c: character; start: positive := 1)
return natural is
begin
if s = null then return 0; end if;
for i in start..s.all'last loop
if s(i) = c then
return i;
end if;
end loop;
return 0;
end match_c;
function match_not_c(s: string_type; c: character; start: positive := 1)
return natural is
begin
if s = null then return 0; end if;
for i in start..s.all'last loop
if s(i) /= c then
return i;
end if;
end loop;
return 0;
end match_not_c;
function match_s(s1, s2: string_type; start: positive := 1)
return natural is
begin
if (s1 = null) or else (s2 = null) then return 0; end if;
return match_string(s1.all, s2.all, start);
end match_s;
function match_s(s1: string_type; s2: string; start: positive := 1)
return natural is
begin
if s1 = null then return 0; end if;
return match_string(s1.all, s2, start);
end match_s;
function match_any(s, any: string_type; start: positive := 1)
return natural is
begin
if any = null then raise any_empty; end if;
return match_any(s, any.all, start);
end match_any;
function match_any(s: string_type; any: string; start: positive := 1)
return natural is
begin
if any = "" then raise any_empty; end if;
if s = null then return 0; end if;
for i in start..s.all'last loop
for j in any'range loop
if s(i) = any(j) then
return i;
end if;
end loop;
end loop;
return 0;
end match_any;
function match_none(s, none: string_type; start: positive := 1)
return natural is
begin
if is_empty(s) then return 0; end if;
if is_empty(none) then return 1; end if;
return match_none(s, none.all, start);
end match_none;
function match_none(s: string_type; none: string; start: positive := 1)
return natural is
found: boolean;
begin
if is_empty(s) then return 0; end if;
for i in start..s.all'last loop
found := true;
for j in none'range loop
if s(i) = none(j) then
found := false;
exit;
end if;
end loop;
if found then return i; end if;
end loop;
return 0;
end match_none;
-- Utilities:
function enter(s: string_type)
return string_type is
begin
-- ATTACHING TO THE END OF THE LIST IS ENTIRELY TOO SLOW AND UNNECESSARY
-- top(scopes).all := attach(top(scopes).all, s);
top(scopes).all := attach(s, top(scopes).all);
return s;
exception
when empty_stack =>
raise illegal_alloc;
end enter;
function match_string(s1, s2: string; start: positive := 1)
return natural is
offset: natural;
begin
offset := s2'length - 1;
for i in start..(s1'last - offset) loop
if s1(i..(i + offset)) = s2 then
return i;
end if;
end loop;
return 0;
exception when constraint_error => -- on offset := s2'length (= 0)
return 0;
end match_string;
begin -- Initialize the scopes stack with an implicit mark.
scopes := create;
mark;
end string_pkg;
-- Module : string_pkg_.ada
-- Component of : common_library
-- Version : 1.2
-- Date : 11/21/86 16:35:52
-- SCCS File : disk21~/rschm/hasee/sccs/common_library/sccs/sxstring_pkg_.ada
-- $Source: /nosc/work/abstractions/string/RCS/string.spc,v $
-- $Revision: 1.1 $ -- $Date: 85/01/10 17:51:46 $ -- $Author: ron $
-- $Source: /nosc/work/abstractions/string/RCS/string.spc,v $
-- $Revision: 1.1 $ -- $Date: 85/01/10 17:51:46 $ -- $Author: ron $
package string_pkg is
--| Overview:
--| Package string_pkg exports an abstract data type, string_type. A
--| string_type value is a sequence of characters. The values have arbitrary
--| length. For a value, s, with length, l, the individual characters are
--| numbered from 1 to l. These values are immutable; characters cannot be
--| replaced or appended in a destructive fashion.
--|
--| In the documentation for this package, we are careful to distinguish
--| between string_type objects, which are Ada objects in the usual sense,
--| and string_type values, the members of this data abstraction as described
--| above. A string_type value is said to be associated with, or bound to,
--| a string_type object after an assignment (:=) operation.
--|
--| The operations provided in this package fall into three categories:
--|
--| 1. Constructors: These functions typically take one or more string_type
--| objects as arguments. They work with the values associated with
--| these objects, and return new string_type values according to
--| specification. By a slight abuse of language, we will sometimes
--| coerce from string_type objects to values for ease in description.
--|
--| 2. Heap Management:
--| These operations (make_persistent, flush, mark, release) control the
--| management of heap space. Because string_type values are
--| allocated on the heap, and the type is not limited, it is necessary
--| for a user to assume some responsibility for garbage collection.
--| String_type is not limited because of the convenience of
--| the assignment operation, and the usefulness of being able to
--| instantiate generic units that contain private type formals.
--| ** Important: To use this package properly, it is necessary to read
--| the descriptions of the operations in this section.
--|
--| 3. Queries: These functions return information about the values
--| that are associated with the argument objects. The same conventions
--| for description of operations used in (1) is adopted.
--|
--| A note about design decisions... The decision to not make the type
--| limited causes two operations to be carried over from the representation.
--| These are the assignment operation, :=, and the "equality" operator, "=".
--| See the discussion at the beginning of the Heap Management section for a
--| discussion of :=.
--| See the spec for the first of the equal functions for a discussion of "=".
--|
--| The following is a complete list of operations, written in the order
--| in which they appear in the spec. Overloaded subprograms are followed
--| by (n), where n is the number of subprograms of that name.
--|
--| 1. Constructors:
--| Empty_String
--| create
--| "&" (3)
--| substr
--| splice
--| insert (3)
--| lower (2)
--| upper (2)
--| mixed (2)
--| 2. Heap Management:
--| make_persistent (2)
--| flush
--| mark, release
--| 3. Queries:
--| is_empty
--| length
--| value
--| fetch
--| equal (3)
--| equivalent (3)
--| "<" (3),
--| "<=" (3)
--| match_c
--| match_not_c
--| match_s (2)
--| match_any (2)
--| match_none (2)
--| Notes:
--| Programmer: Ron Kownacki
type string_type is private;
bounds: exception; --| Raised on index out of bounds.
any_empty: exception; --| Raised on incorrect use of match_any.
illegal_alloc: exception; --| Raised by value creating operations.
illegal_dealloc: exception; --| Raised by release.
-- Constructors:
function Empty_String return String_Type;
--| Raises: Illegal_Alloc
--| Effects: returns String_Pkg.Create ("");
pragma Inline (Empty_String);
function create(s: string)
return string_type;
--| Raises: illegal_alloc
--| Effects:
--| Return a value consisting of the sequence of characters in s.
--| Sometimes useful for array or record aggregates.
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function "&"(s1, s2: string_type)
return string_type;
--| Raises: illegal_alloc
--| Effects:
--| Return the concatenation of s1 and s2.
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function "&"(s1: string_type; s2: string)
return string_type;
--| Raises: illegal_alloc
--| Effects:
--| Return the concatenation of s1 and create(s2).
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function "&"(s1: string; s2: string_type)
return string_type;
--| Raises: illegal_alloc
--| Effects:
--| Return the concatenation of create(s1) and s2.
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function substr(s: string_type; i: positive; len: natural)
return string_type;
--| Raises: bounds, illegal_alloc
--| Effects:
--| Return the substring, of specified length, that occurs in s at
--| position i. If len = 0, then returns the empty value.
--| Otherwise, raises bounds if either i or (i + len - 1)
--| is not in 1..length(s).
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function splice(s: string_type; i: positive; len: natural)
return string_type;
--| Raises: bounds, illegal_alloc
--| Effects:
--| Let s be the string, abc, where a, b and c are substrings. If
--| substr(s, i, length(b)) = b, for some i in 1..length(s), then
--| splice(s, i, length(b)) = ac.
--| Returns a value equal to s if len = 0. Otherwise, raises bounds if
--| either i or (i + len - 1) is not in 1..length(s).
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function insert(s1, s2: string_type; i: positive)
return string_type;
--| Raises: bounds, illegal_alloc
--| Effects:
--| Return substr(s1, 1, i - 1) & s2 &
--| substr(s1, i, length(s1) - i + 1).
--| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
--| exception is raised by insert.
--| Raises bounds if is_empty(s1) or else i is not in 1..length(s1).
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function insert(s1: string_type; s2: string; i: positive)
return string_type;
--| Raises: bounds, illegal_alloc
--| Effects:
--| Return substr(s1, 1, i - 1) & s2 &
--| substr(s1, i, length(s1) - i + 1).
--| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
--| exception is raised by insert.
--| Raises bounds if is_empty(s1) or else i is not in 1..length(s1).
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function insert(s1: string; s2: string_type; i: positive)
return string_type;
--| Raises: bounds, illegal_alloc
--| Effects:
--| Return s1(s1'first..i - 1) & s2 &
--| s1(i..length(s1) - i + 1).
--| equal(splice(insert(s1, s2, i), i, length(s2)), s1) holds if no
--| exception is raised by insert.
--| Raises bounds if i is not in s'range.
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function lower(s: string)
return string_type;
--| Raises: illegal_alloc
--| Effects:
--| Return a value that contains exactly those characters in s with
--| the exception that all upper case characters are replaced by their
--| lower case counterparts.
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function lower(s: string_type)
return string_type;
--| Raises: illegal_alloc
--| Effects:
--| Return a value that is a copy of s with the exception that all
--| upper case characters are replaced by their lower case counterparts.
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function upper(s: string)
return string_type;
--| Raises: illegal_alloc
--| Effects:
--| Return a value that contains exactly those characters in s with
--| the exception that all lower case characters are replaced by their
--| upper case counterparts.
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function upper(s: string_type)
return string_type;
--| Raises: illegal_alloc
--| Effects:
--| Return a value that is a copy of s with the exception that all
--| lower case characters are replaced by their upper case counterparts.
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function Mixed (S: String)
return String_Type;
--| Raises: Illegal_Alloc
--| Effects:
--| Return a value that contains exactly those characters in s with
--| the exception that all upper case characters are replaced by their
--| lower case counterparts with the exception of the first character and
--| each character following an underscore which are forced to upper case.
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
function Mixed (S: String_Type)
return String_Type;
--| Raises: Illegal_Alloc
--| Effects:
--| Return a value that contains exactly those characters in s with
--| the exception that all upper case characters are replaced by their
--| lower case counterparts with the exception of the first character and
--| each character following an underscore which are forced to upper case.
--| Raises illegal_alloc if string space has been improperly
--| released. (See procedures mark/release.)
-- Heap Management (including object/value binding):
--
-- Two forms of heap management are provided. The general scheme is to "mark"
-- the current state of heap usage, and to "release" in order to reclaim all
-- space that has been used since the last mark. However, this alone is
-- insufficient because it is frequently desirable for objects to remain
-- associated with values for longer periods of time, and this may come into
-- conflict with the need to clean up after a period of "string hacking."
-- To deal with this problem, we introduce the notions of "persistent" and
-- "nonpersistent" values.
--
-- The nonpersistent values are those that are generated by the constructors
-- in the previous section. These are claimed by the release procedure.
-- Persistent values are generated by the two make_persistent functions
-- described below. These values must be disposed of individually by means of
-- the flush procedure.
--
-- This allows a description of the meaning of the ":=" operation. For a
-- statement of the form, s := expr, where expr is a string_type expression,
-- the result is that the value denoted/created by expr becomes bound to the
-- the object, s. Assignment in no way affects the persistence of the value.
-- If expr happens to be an object, then the value associated with it will be
-- shared. Ideally, this sharing would not be visible, since values are
-- immutable. However, the sharing may be visible because of the memory
-- management, as described below. Programs which depend on such sharing are
-- erroneous.
function make_persistent(s: string_type)
return string_type;
--| Effects:
--| Returns a persistent value, v, containing exactly those characters in
--| value(s). The value v will not be claimed by any subsequent release.
--| Only an invocation of flush will claim v. After such a claiming
--| invocation of flush, the use (other than :=) of any other object to
--| which v was bound is erroneous, and program_error may be raised for
--| such a use.
function make_persistent(s: string)
return string_type;
--| Effects:
--| Returns a persistent value, v, containing exactly those chars in s.
--| The value v will not be claimed by any subsequent release.
--| Only an invocation of flush will reclaim v. After such a claiming
--| invocation of flush, the use (other than :=) of any other object to
--| which v was bound is erroneous, and program_error may be raised for
--| such a use.
procedure flush(s: in out string_type);
--| Effects:
--| Return heap space used by the value associated with s, if any, to
--| the heap. s becomes associated with the empty value. After an
--| invocation of flush claims the value, v, then any use (other than :=)
--| of an object to which v was bound is erroneous, and program_error
--| may be raised for such a use.
--|
--| This operation should be used only for persistent values. The mark
--| and release operations are used to deallocate space consumed by other
--| values. For example, flushing a nonpersistent value implies that a
--| release that tries to claim this value will be erroneous, and
--| program_error may be raised for such a use.
procedure mark;
--| Effects:
--| Marks the current state of heap usage for use by release.
--| An implicit mark is performed at the beginning of program execution.
procedure release;
--| Raises: illegal_dealloc
--| Effects:
--| Releases all heap space used by nonpersistent values that have been
--| allocated since the last mark. The values that are claimed include
--| those bound to objects as well as those produced and discarded during
--| the course of general "string hacking." If an invocation of release
--| claims a value, v, then any subsequent use (other than :=) of any
--| other object to which v is bound is erroneous, and program_error may
--| be raised for such a use.
--|
--| Raises illegal_dealloc if the invocation of release does not balance
--| an invocation of mark. It is permissible to match the implicit
--| initial invocation of mark. However, subsequent invocations of
--| constructors will raise the illegal_alloc exception until an
--| additional mark is performed. (Anyway, there is no good reason to
--| do this.) In any case, a number of releases matching the number of
--| currently active marks is implicitly performed at the end of program
--| execution.
--|
--| Good citizens generally perform their own marks and releases
--| explicitly. Extensive string hacking without cleaning up will
--| cause your program to run very slowly, since the heap manager will
--| be forced to look hard for chunks of space to allocate.
-- Queries:
function is_empty(s: string_type)
return boolean;
--| Effects:
--| Return true iff s is the empty sequence of characters.
function length(s: string_type)
return natural;
--| Effects:
--| Return number of characters in s.
function value(s: string_type)
return string;
--| Effects:
--| Return a string, s2, that contains the same characters that s
--| contains. The properties, s2'first = 1 and s2'last = length(s),
--| are satisfied. This implies that, for a given string, s3,
--| value(create(s3))'first may not equal s3'first, even though
--| value(create(s3)) = s3 holds. Thus, "content equality" applies
--| although the string objects may be distinguished by the use of
--| the array attributes.
function fetch(s: string_type; i: positive)
return character;
--| Raises: bounds
--| Effects:
--| Return the ith character in s. Characters are numbered from
--| 1 to length(s). Raises bounds if i not in 1..length(s).
function equal(s1, s2: string_type)
return boolean;
--| Effects:
--| Value equality relation; return true iff length(s1) = length(s2)
--| and, for all i in 1..length(s1), fetch(s1, i) = fetch(s2, i).
--| The "=" operation is carried over from the representation.
--| It allows one to distinguish among the heap addresses of
--| string_type values. Even "equal" values may not be "=", although
--| s1 = s2 implies equal(s1, s2).
--| There is no reason to use "=".
function equal(s1: string_type; s2: string)
return boolean;
--| Effects:
--| Return equal(s1, create(s2)).
function equal(s1: string; s2: string_type)
return boolean;
--| Effects:
--| Return equal(create(s1), s2).
--|===========================================================================
--| Overview: Equivalent is the Case Insensitive version of Equal
function Equivalent (Left, Right : in String_Type) return Boolean;
function Equivalent (Left : in String;
Right : in String_Type) return Boolean;
function Equivalent (Left : in String_Type;
Right : in String) return Boolean;
--|===========================================================================
function "<"(s1: string_type; s2: string_type)
return boolean;
--| Effects:
--| Lexicographic comparison; return value(s1) < value(s2).
function "<"(s1: string_type; s2: string)
return boolean;
--| Effects:
--| Lexicographic comparison; return value(s1) < s2.
function "<"(s1: string; s2: string_type)
return boolean;
--| Effects:
--| Lexicographic comparison; return s1 < value(s2).
function "<="(s1: string_type; s2: string_type)
return boolean;
--| Effects:
--| Lexicographic comparison; return value(s1) <= value(s2).
function "<="(s1: string_type; s2: string)
return boolean;
--| Effects:
--| Lexicographic comparison; return value(s1) <= s2.
function "<="(s1: string; s2: string_type)
return boolean;
--| Effects:
--| Lexicographic comparison; return s1 <= value(s2).
function match_c(s: string_type; c: character; start: positive := 1)
return natural;
--| Raises: no_match
--| Effects:
--| Return the minimum index, i in start..length(s), such that
--| fetch(s, i) = c. Returns 0 if no such i exists,
--| including the case where is_empty(s).
function match_not_c(s: string_type; c: character; start: positive := 1)
return natural;
--| Raises: no_match
--| Effects:
--| Return the minimum index, i in start..length(s), such that
--| fetch(s, i) /= c. Returns 0 if no such i exists,
--| including the case where is_empty(s).
function match_s(s1, s2: string_type; start: positive := 1)
return natural;
--| Raises: no_match.
--| Effects:
--| Return the minimum index, i, in start..length(s1), such that,
--| for all j in 1..length(s2), fetch(s2, j) = fetch(s1, i + j - 1).
--| This is the position of the substring, s2, in s1.
--| Returns 0 if no such i exists, including the cases
--| where is_empty(s1) or is_empty(s2).
--| Note that equal(substr(s1, match_s(s1, s2, i), length(s2)), s2)
--| holds, providing that match_s does not raise an exception.
function match_s(s1: string_type; s2: string; start: positive := 1)
return natural;
--| Raises: no_match.
--| Effects:
--| Return the minimum index, i, in start..length(s1), such that,
--| for all j in s2'range, s2(j) = fetch(s1, i + j - 1).
--| This is the position of the substring, s2, in s1.
--| Returns 0 if no such i exists, including the cases
--| where is_empty(s1) or s2 = "".
--| Note that equal(substr(s1, match_s(s1, s2, i), s2'length), s2)
--| holds, providing that match_s does not raise an exception.
function match_any(s, any: string_type; start: positive := 1)
return natural;
--| Raises: no_match, any_empty
--| Effects:
--| Return the minimum index, i in start..length(s), such that
--| fetch(s, i) = fetch(any, j), for some j in 1..length(any).
--| Raises any_empty if is_empty(any).
--| Otherwise, returns 0 if no such i exists, including the case
--| where is_empty(s).
function match_any(s: string_type; any: string; start: positive := 1)
return natural;
--| Raises: no_match, any_empty
--| Effects:
--| Return the minimum index, i, in start..length(s), such that
--| fetch(s, i) = any(j), for some j in any'range.
--| Raises any_empty if any = "".
--| Otherwise, returns 0 if no such i exists, including the case
--| where is_empty(s).
function match_none(s, none: string_type; start: positive := 1)
return natural;
--| Raises: no_match
--| Effects:
--| Return the minimum index, i in start..length(s), such that
--| fetch(s, i) /= fetch(none, j) for each j in 1..length(none).
--| If (not is_empty(s)) and is_empty(none), then i is 1.
--| Returns 0 if no such i exists, including the case
--| where is_empty(s).
function match_none(s: string_type; none: string; start: positive := 1)
return natural;
--| Raises: no_match.
--| Effects:
--| Return the minimum index, i in start..length(s), such that
--| fetch(s, i) /= none(j) for each j in none'range.
--| If not is_empty(s) and none = "", then i is 1.
--| Returns 0 if no such i exists, including the case
--| where is_empty(s).
private
type string_type is access string;
--| Abstract data type, string_type, is a constant sequence of chars
--| of arbitrary length. Representation type is access string.
--| It is important to distinguish between an object of the rep type
--| and its value; for an object, r, val(r) denotes the value.
--|
--| Representation Invariant: I: rep --> boolean
--| I(r: rep) = (val(r) = null) or else
--| (val(r).all'first = 1 &
--| val(r).all'last >= 0 &
--| (for all r2, val(r) = val(r2) /= null => r is r2))
--|
--| Abstraction Function: A: rep --> string_type
--| A(r: rep) = if r = null then
--| the empty sequence
--| elsif r'last = 0 then
--| the empty sequence
--| else
--| the sequence consisting of r(1),...,r(r'last).
end string_pkg;
-- Module : string_scanner.ada
-- Component of : common_library
-- Version : 1.2
-- Date : 11/21/86 16:36:26
-- SCCS File : disk21~/rschm/hasee/sccs/common_library/sccs/sxstring_scanner.ada
with String_Pkg; use String_Pkg;
with Unchecked_Deallocation;
package body String_Scanner is
SCCS_ID : constant String := "@(#) string_scanner.ada, Version 1.2";
White_Space : constant string := " " & ASCII.HT;
Number_1 : constant string := "0123456789";
Number : constant string := Number_1 & "_";
Quote : constant string := """";
Ada_Id_1 : constant string := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
Ada_Id : constant string := Ada_Id_1 & Number;
procedure Free_Scanner is
new Unchecked_Deallocation(Scan_Record, Scanner);
pragma Page;
function Is_Valid(
T : in Scanner
) return boolean is
begin
return T /= null;
end Is_Valid;
function Make_Scanner(
S : in String_Type
) return Scanner is
T : Scanner := new Scan_Record;
begin
T.text := String_Pkg.Make_Persistent(S);
return T;
end Make_Scanner;
----------------------------------------------------------------
procedure Destroy_Scanner(
T : in out Scanner
) is
begin
if Is_Valid(T) then
String_Pkg.Flush(T.text);
Free_Scanner(T);
end if;
end Destroy_Scanner;
----------------------------------------------------------------
function More(
T : in Scanner
) return boolean is
begin
if Is_Valid(T) then
if T.index > String_Pkg.Length(T.text) then
return false;
else
return true;
end if;
else
return false;
end if;
end More;
----------------------------------------------------------------
function Get(
T : in Scanner
) return character is
begin
if not More(T) then
raise Out_Of_Bounds;
end if;
return String_Pkg.Fetch(T.text, T.index);
end Get;
----------------------------------------------------------------
procedure Forward(
T : in Scanner
) is
begin
if Is_Valid(T) then
if String_Pkg.Length(T.text) >= T.index then
T.index := T.index + 1;
end if;
end if;
end Forward;
----------------------------------------------------------------
procedure Backward(
T : in Scanner
) is
begin
if Is_Valid(T) then
if T.index > 1 then
T.index := T.index - 1;
end if;
end if;
end Backward;
----------------------------------------------------------------
procedure Next(
T : in Scanner;
C : out character
) is
begin
C := Get(T);
Forward(T);
end Next;
----------------------------------------------------------------
function Position(
T : in Scanner
) return positive is
begin
if not More(T) then
raise Out_Of_Bounds;
end if;
return T.index;
end Position;
----------------------------------------------------------------
function Get_String(
T : in Scanner
) return String_Type is
begin
if Is_Valid(T) then
return String_Pkg.Make_Persistent(T.text);
else
return String_Pkg.Make_Persistent("");
end if;
end Get_String;
----------------------------------------------------------------
function Get_Remainder(
T : in Scanner
) return String_Type is
S_Str : String_Type;
begin
if More(T) then
String_Pkg.Mark;
S_Str := String_Pkg.Make_Persistent(
String_Pkg.Substr(T.text,
T.index,
String_Pkg.Length(T.text) - T.index + 1));
String_Pkg.Release;
else
S_Str := String_Pkg.Make_Persistent("");
end if;
return S_Str;
end Get_Remainder;
----------------------------------------------------------------
procedure Mark(
T : in Scanner
) is
begin
if Is_Valid(T) then
if T.mark /= 0 then
raise Scanner_Already_Marked;
else
T.mark := T.index;
end if;
end if;
end Mark;
----------------------------------------------------------------
procedure Restore(
T : in Scanner
) is
begin
if Is_Valid(T) then
if T.mark /= 0 then
T.index := T.mark;
T.mark := 0;
end if;
end if;
end Restore;
pragma Page;
function Is_Any(
T : in Scanner;
Q : in string
) return boolean is
N : natural;
begin
if not More(T) then
return false;
end if;
String_Pkg.Mark;
N := String_Pkg.Match_Any(T.text, Q, T.index);
if N /= T.index then
N := 0;
end if;
String_Pkg.Release;
return N /= 0;
end Is_Any;
pragma Page;
procedure Scan_Any(
T : in Scanner;
Q : in string;
Found : out boolean;
Result : in out String_Type
) is
S_Str : String_Type;
N : natural;
begin
if Is_Any(T, Q) then
N := String_Pkg.Match_None(T.text, Q, T.index);
if N = 0 then
N := String_Pkg.Length(T.text) + 1;
end if;
Result := Result & String_Pkg.Substr(T.text, T.index, N - T.index);
T.index := N;
Found := true;
else
Found := false;
end if;
end Scan_Any;
pragma Page;
function Quoted_String(
T : in Scanner
) return integer is
Count : integer := 0;
I : positive;
N : natural;
begin
if not Is_Valid(T) then
return Count;
end if;
I := T.index;
while Is_Any(T, """") loop
T.index := T.index + 1;
if not More(T) then
T.index := I;
return 0;
end if;
String_Pkg.Mark;
N := String_Pkg.Match_Any(T.text, """", T.index);
String_Pkg.Release;
if N = 0 then
T.index := I;
return 0;
end if;
T.index := N + 1;
end loop;
Count := T.index - I;
T.index := I;
return Count;
end Quoted_String;
pragma Page;
function Enclosed_String(
B : in character;
E : in character;
T : in Scanner
) return natural is
Count : natural := 1;
I : positive;
Inx_B : natural;
Inx_E : natural;
Depth : natural := 1;
begin
if not Is_Any(T, B & "") then
return 0;
end if;
I := T.index;
Forward(T);
while Depth /= 0 loop
if not More(T) then
T.index := I;
return 0;
end if;
String_Pkg.Mark;
Inx_B := String_Pkg.Match_Any(T.text, B & "", T.index);
Inx_E := String_Pkg.Match_Any(T.text, E & "", T.index);
String_Pkg.Release;
if Inx_E = 0 then
T.index := I;
return 0;
end if;
if Inx_B /= 0 and then Inx_B < Inx_E then
Depth := Depth + 1;
else
Inx_B := Inx_E;
Depth := Depth - 1;
end if;
T.index := Inx_B + 1;
end loop;
Count := T.index - I;
T.index := I;
return Count;
end Enclosed_String;
pragma Page;
function Is_Word(
T : in Scanner
) return boolean is
begin
if not More(T) then
return false;
else
return not Is_Any(T, White_Space);
end if;
end Is_Word;
----------------------------------------------------------------
procedure Scan_Word(
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
S_Str : String_Type;
N : natural;
begin
if Skip then
Skip_Space(T);
end if;
if Is_Word(T) then
String_Pkg.Mark;
N := String_Pkg.Match_Any(T.text, White_Space, T.index);
if N = 0 then
N := String_Pkg.Length(T.text) + 1;
end if;
Result := String_Pkg.Make_Persistent
(String_Pkg.Substr(T.text, T.index, N - T.index));
T.index := N;
Found := true;
String_Pkg.Release;
else
Found := false;
end if;
return;
end Scan_Word;
pragma Page;
function Is_Number(
T : in Scanner
) return boolean is
begin
return Is_Any(T, Number_1);
end Is_Number;
----------------------------------------------------------------
procedure Scan_Number(
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
C : character;
S_Str : String_Type;
begin
if Skip then
Skip_Space(T);
end if;
if not Is_Number(T) then
Found := false;
return;
end if;
String_Pkg.Mark;
while Is_Number(T) loop
Scan_Any(T, Number_1, Found, S_Str);
if More(T) then
C := Get(T);
if C = '_' then
Forward(T);
if Is_Number(T) then
S_Str := S_Str & "_";
else
Backward(T);
end if;
end if;
end if;
end loop;
Result := String_Pkg.Make_Persistent(S_Str);
String_Pkg.Release;
end Scan_Number;
----------------------------------------------------------------
procedure Scan_Number(
T : in Scanner;
Found : out boolean;
Result : out integer;
Skip : in boolean := false
) is
F : boolean;
S_Str : String_Type;
begin
Scan_Number(T, F, S_Str, Skip);
if F then
Result := integer'value(String_Pkg.Value(S_Str));
end if;
Found := F;
end Scan_Number;
pragma Page;
function Is_Signed_Number(
T : in Scanner
) return boolean is
I : positive;
C : character;
F : boolean;
begin
if More(T) then
I := T.index;
C := Get(T);
if C = '+' or C = '-' then
T.index := T.index + 1;
end if;
F := Is_Any(T, Number_1);
T.index := I;
return F;
else
return false;
end if;
end Is_Signed_Number;
----------------------------------------------------------------
procedure Scan_Signed_Number(
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
C : character;
S_Str : String_Type;
begin
if Skip then
Skip_Space(T);
end if;
if Is_Signed_Number(T) then
C := Get(T);
if C = '+' or C = '-' then
Forward(T);
end if;
Scan_Number(T, Found, S_Str);
String_Pkg.Mark;
if C = '+' or C = '-' then
Result := String_Pkg.Make_Persistent(("" & C) & S_Str);
else
Result := String_Pkg.Make_Persistent(S_Str);
end if;
String_Pkg.Release;
String_Pkg.Flush(S_Str);
else
Found := false;
end if;
end Scan_Signed_Number;
----------------------------------------------------------------
procedure Scan_Signed_Number(
T : in Scanner;
Found : out boolean;
Result : out integer;
Skip : in boolean := false
) is
F : boolean;
S_Str : String_Type;
begin
Scan_Signed_Number(T, F, S_Str, Skip);
if F then
Result := integer'value(String_Pkg.Value(S_Str));
end if;
Found := F;
end Scan_Signed_Number;
pragma Page;
function Is_Space(
T : in Scanner
) return boolean is
begin
return Is_Any(T, White_Space);
end Is_Space;
----------------------------------------------------------------
procedure Scan_Space(
T : in Scanner;
Found : out boolean;
Result : out String_Type
) is
S_Str : String_Type;
begin
String_Pkg.Mark;
Scan_Any(T, White_Space, Found, S_Str);
Result := String_Pkg.Make_Persistent(S_Str);
String_Pkg.Release;
end Scan_Space;
----------------------------------------------------------------
procedure Skip_Space(
T : in Scanner
) is
S_Str : String_Type;
Found : boolean;
begin
String_Pkg.Mark;
Scan_Any(T, White_Space, Found, S_Str);
String_Pkg.Release;
end Skip_Space;
pragma Page;
function Is_Ada_Id(
T : in Scanner
) return boolean is
begin
return Is_Any(T, Ada_Id_1);
end Is_Ada_Id;
----------------------------------------------------------------
procedure Scan_Ada_Id(
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
C : character;
F : boolean;
S_Str : String_Type;
begin
if Skip then
Skip_Space(T);
end if;
if Is_Ada_Id(T) then
String_Pkg.Mark;
Next(T, C);
Scan_Any(T, Ada_Id, F, S_Str);
Result := String_Pkg.Make_Persistent(("" & C) & S_Str);
Found := true;
String_Pkg.Release;
else
Found := false;
end if;
end Scan_Ada_Id;
pragma Page;
function Is_Quoted(
T : in Scanner
) return boolean is
begin
if Quoted_String(T) = 0 then
return false;
else
return true;
end if;
end Is_Quoted;
----------------------------------------------------------------
procedure Scan_Quoted(
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
Count : integer;
begin
if Skip then
Skip_Space(T);
end if;
Count := Quoted_String(T);
if Count /= 0 then
Count := Count - 2;
T.index := T.index + 1;
if Count /= 0 then
String_Pkg.Mark;
Result := String_Pkg.Make_Persistent
(String_Pkg.Substr(T.text, T.index, positive(Count)));
String_Pkg.Release;
else
Result := String_Pkg.Make_Persistent("");
end if;
T.index := T.index + Count + 1;
Found := true;
else
Found := false;
end if;
end Scan_Quoted;
pragma Page;
function Is_Enclosed(
B : in character;
E : in character;
T : in Scanner
) return boolean is
begin
if Enclosed_String(B, E, T) = 0 then
return false;
else
return true;
end if;
end Is_Enclosed;
----------------------------------------------------------------
procedure Scan_Enclosed(
B : in character;
E : in character;
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
Count : natural;
begin
if Skip then
Skip_Space(T);
end if;
Count := Enclosed_String(B, E, T);
if Count /= 0 then
Count := Count - 2;
T.index := T.index + 1;
if Count /= 0 then
String_Pkg.Mark;
Result := String_Pkg.Make_Persistent(String_Pkg.Substr(T.text, T.index, positive(Count)));
String_Pkg.Release;
else
Result := String_Pkg.Make_Persistent("");
end if;
T.index := T.index + Count + 1;
Found := true;
else
Found := false;
end if;
end Scan_Enclosed;
pragma Page;
function Is_Sequence(
Chars : in String_Type;
T : in Scanner
) return boolean is
begin
return Is_Any(T, String_Pkg.Value(Chars));
end Is_Sequence;
----------------------------------------------------------------
function Is_Sequence(
Chars : in string;
T : in Scanner
) return boolean is
begin
return Is_Any(T, Chars);
end Is_Sequence;
----------------------------------------------------------------
procedure Scan_Sequence(
Chars : in String_Type;
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
I : positive;
Count : integer := 0;
begin
if Skip then
Skip_Space(T);
end if;
if not Is_Valid(T) then
Found := false;
return;
end if;
I := T.index;
while Is_Any(T, Value(Chars)) loop
Forward(T);
Count := Count + 1;
end loop;
if Count /= 0 then
String_Pkg.Mark;
Result := String_Pkg.Make_Persistent
(String_Pkg.Substr(T.text, I, positive(Count)));
Found := true;
String_Pkg.Release;
else
Found := false;
end if;
end Scan_Sequence;
----------------------------------------------------------------
procedure Scan_Sequence(
Chars : in string;
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
begin
String_Pkg.Mark;
Scan_Sequence(String_Pkg.Create(Chars), T, Found, Result, Skip);
String_Pkg.Release;
end Scan_Sequence;
pragma Page;
function Is_Not_Sequence(
Chars : in String_Type;
T : in Scanner
) return boolean is
N : natural;
begin
if not Is_Valid(T) then
return false;
end if;
String_Pkg.Mark;
N := String_Pkg.Match_Any(T.text, Chars, T.index);
if N = T.index then
N := 0;
end if;
String_Pkg.Release;
return N /= 0;
end Is_Not_Sequence;
----------------------------------------------------------------
function Is_Not_Sequence(
Chars : in string;
T : in Scanner
) return boolean is
begin
return Is_Not_Sequence(String_Pkg.Create(Chars), T);
end Is_Not_Sequence;
----------------------------------------------------------------
procedure Scan_Not_Sequence(
Chars : in string;
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
N : natural;
begin
if Skip then
Skip_Space(T);
end if;
if Is_Not_Sequence(Chars, T) then
String_Pkg.Mark;
N := String_Pkg.Match_Any(T.text, Chars, T.index);
Result := String_Pkg.Make_Persistent
(String_Pkg.Substr(T.text, T.index, N - T.index));
T.index := N;
Found := true;
String_Pkg.Release;
else
Found := false;
end if;
end Scan_Not_Sequence;
----------------------------------------------------------------
procedure Scan_Not_Sequence(
Chars : in String_Type;
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
begin
Scan_Not_Sequence(String_Pkg.Value(Chars), T, Found, Result, Skip);
end Scan_Not_Sequence;
pragma Page;
function Is_Literal(
Chars : in String_Type;
T : in Scanner
) return boolean is
N : natural;
begin
if not Is_Valid(T) then
return false;
end if;
String_Pkg.Mark;
N := String_Pkg.Match_S(T.text, Chars, T.index);
if N /= T.index then
N := 0;
end if;
String_Pkg.Release;
return N /= 0;
end Is_Literal;
----------------------------------------------------------------
function Is_Literal(
Chars : in string;
T : in Scanner
) return boolean is
Found : boolean;
begin
String_Pkg.Mark;
Found := Is_Literal(String_Pkg.Create(Chars), T);
String_Pkg.Release;
return Found;
end Is_Literal;
----------------------------------------------------------------
procedure Scan_Literal(
Chars : in String_Type;
T : in Scanner;
Found : out boolean;
Skip : in boolean := false
) is
begin
if Skip then
Skip_Space(T);
end if;
if Is_Literal(Chars, T) then
T.index := T.index + String_Pkg.Length(Chars);
Found := true;
else
Found := false;
end if;
end Scan_Literal;
----------------------------------------------------------------
procedure Scan_Literal(
Chars : in string;
T : in Scanner;
Found : out boolean;
Skip : in boolean := false
) is
begin
String_Pkg.Mark;
Scan_Literal(String_Pkg.Create(Chars), T, Found, Skip);
String_Pkg.Release;
end Scan_Literal;
pragma Page;
function Is_Not_Literal(
Chars : in string;
T : in Scanner
) return boolean is
N : natural;
begin
if not Is_Valid(T) then
return false;
end if;
String_Pkg.Mark;
N := String_Pkg.Match_S(T.text, Chars, T.index);
if N = T.index then
N := 0;
end if;
String_Pkg.Release;
return N /= 0;
end Is_Not_Literal;
----------------------------------------------------------------
function Is_Not_Literal(
Chars : in String_Type;
T : in Scanner
) return boolean is
begin
if not More(T) then
return false;
end if;
return Is_Not_Literal(String_Pkg.Value(Chars), T);
end Is_Not_Literal;
----------------------------------------------------------------
procedure Scan_Not_Literal(
Chars : in string;
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
N : natural;
begin
if Skip then
Skip_Space(T);
end if;
if Is_Not_Literal(Chars, T) then
String_Pkg.Mark;
N := String_Pkg.Match_S(T.text, Chars, T.index);
Result := String_Pkg.Make_Persistent(String_Pkg.Substr(T.text, T.index, N - T.index));
T.index := N;
Found := true;
String_Pkg.Release;
else
Found := false;
return;
end if;
end Scan_Not_Literal;
----------------------------------------------------------------
procedure Scan_Not_Literal(
Chars : in String_Type;
T : in Scanner;
Found : out boolean;
Result : out String_Type;
Skip : in boolean := false
) is
begin
Scan_Not_Literal(String_Pkg.Value(Chars), T, Found, Result, Skip);
end Scan_Not_Literal;
end String_Scanner;
pragma Page;
-- Module : string_scanner_.ada
-- Component of : common_library
-- Version : 1.2
-- Date : 11/21/86 16:37:08
-- SCCS File : disk21~/rschm/hasee/sccs/common_library/sccs/sxstring_scanner_.ada
with String_Pkg; use String_Pkg;
package String_Scanner is
--| Functions for scanning tokens from strings.
pragma Page;
--| Overview
--| This package provides a set of functions used to scan tokens from
--| strings. After the function make_Scanner is called to convert a string
--| into a string Scanner, the following functions may be called to scan
--| various tokens from the string:
--|-
--| Make_Scanner Given a string returns a Scanner
--| Destroy_Scanner Free storage used by Scanner
--| More Return TRUE iff unscanned characters remain
--| Forward Bump the Scanner
--| Backward Bump back the Scanner
--| Get Return character
--| Next Return character and bump the Scanner
--| Get_String Return String_Type in Scanner
--| Get_Remainder Return String_Type in Scanner from current Index
--| Mark Mark the current Index for Restore
--| Restore Restore the previously marked Index
--| Position Return the current position of the Scanner
--| Is_Word Return TRUE iff Scanner is at a non-blank character
--| Scan_Word Return sequence of non blank characters
--| Is_Number Return TRUE iff Scanner is at a digit
--| Scan_Number (2) Return sequence of decimal digits
--| Is_Signed_Number Return TRUE iff Scanner is at a digit or sign
--| Scan_Signed_Number (2)
--| sequence of decimal digits with optional sign (+/-)
--| Is_Space Return TRUE iff Scanner is at a space or tab
--| Scan_Space Return sequence of spaces or tabs
--| Skip_Space Advance Scanner past white space
--| Is_Ada_Id Return TRUE iff Scanner is at first character of ada id
--| Scan_Ada_Id Scan an Ada identifier
--| Is_Quoted Return TRUE iff Scanner is at a double quote
--| Scan_Quoted Scan quoted string, embedded quotes doubled
--| Is_Enclosed Return TRUE iff Scanner is at an enclosing character
--| Scan_Enclosed Scan enclosed string, embedded enclosing character doubled
--| Is_Sequence Return TRUE iff Scanner is at some character in sequence
--| Scan_Sequence Scan user specified sequence of chars
--| Is_Not_Sequence Return TRUE iff Scanner is not at the characters in sequence
--| Scan_Not_Sequence Scan string up to but not including a given sequence of chars
--| Is_Literal Return TRUE iff Scanner is at literal
--| Scan_Literal Scan user specified literal
--| Is_Not_Literal Return TRUE iff Scanner is not a given literal
--| Scan_Not_Literal Scan string up to but not including a given literal
--|+
----------------------------------------------------------------
Out_Of_Bounds : exception; --| Raised when a operation is attempted on a
--| Scanner that has passed the end
Scanner_Already_Marked : exception;
--| Raised when a Mark is attemped on a Scanner
--| that has already been marked
----------------------------------------------------------------
type Scanner is private; --| Scanner type
----------------------------------------------------------------
pragma Page;
function Make_Scanner( --| Construct a Scanner from S.
S : in String_Type --| String to be scanned.
) return Scanner;
--| Effects: Construct a Scanner from S.
--| N/A: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Destroy_Scanner( --| Free Scanner storage
T : in out Scanner --| Scanner to be freed
);
--| Effects: Free space occupied by the Scanner.
--| N/A: Raises, Modifies, Errors
----------------------------------------------------------------
function More( --| Check if Scanner is exhausted
T : in Scanner --| Scanner to check
) return boolean;
--| Effects: Return TRUE iff additional characters remain to be scanned.
--| N/A: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Forward( --| Bump scanner
T : in Scanner --| Scanner
);
--| Effects: Update the scanner position.
--| N/A: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Backward( --| Bump back scanner
T : in Scanner --| Scanner
);
--| Effects: Update the scanner position.
--| N/A: Raises, Modifies, Errors
----------------------------------------------------------------
function Get( --| Return character
T : in Scanner --| Scanner to check
) return character;
--| Raises: Out_Of_Bounds
--| Effects: Return character at the current Scanner position.
--| The scanner position remains unchanged.
--| N/A: Modifies, Errors
----------------------------------------------------------------
procedure Next( --| Return character and bump scanner
T : in Scanner; --| Scanner to check
C : out character --| Character to be returned
);
--| Raises: Out_Of_Bounds
--| Effects: Return character at the current Scanner position and update
--| the position.
--| N/A: Modifies, Errors
----------------------------------------------------------------
function Position( --| Return current Scanner position
T : in Scanner --| Scanner to check
) return positive;
--| Raises: Out_Of_Bounds
--| Effects: Return a positive integer indicating the current Scanner position,
--| N/A: Modifies, Errors
----------------------------------------------------------------
function Get_String( --| Return contents of Scanner
T : in Scanner --| Scanner
) return String_Type;
--| Effects: Return a String_Type corresponding to the contents of the Scanner
--| N/A: Raises, Modifies, Errors
----------------------------------------------------------------
function Get_Remainder( --| Return contents of Scanner from index
T : in Scanner
) return String_Type;
--| Effects: Return a String_Type starting at the current index of the Scanner
--| N/A: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Mark(
T : in Scanner
);
--| Raises: Scanner_Already_Marked
--| Effects: Mark the current index for possible future use
--| N/A: Modifies, Errors
----------------------------------------------------------------
procedure Restore(
T : in Scanner
);
--| Effects: Restore the index to the previously marked value
--| N/A: Raises, Modifies, Errors
----------------------------------------------------------------
pragma Page;
function Is_Word( --| Check if Scanner is at the start of a word.
T : in Scanner --| Scanner to check
) return boolean;
--| Effects: Return TRUE iff Scanner is at the start of a word.
--| N/A: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_word( --| Scan sequence of non blank characters
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff a word found
Result : out String_Type;--| Word scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a sequence of non blank
--| characters. If at least one is found, return Found => TRUE,
--| Result => <the characters>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| N/A: Raises, Modifies, Errors
pragma Page;
function Is_Number( --| Return TRUE iff Scanner is at a decimal digit
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff Scan_Number would return a non-null string.
--| N/A: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Number( --| Scan sequence of digits
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff one or more digits found
Result : out String_Type;--| Number scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a sequence of digits.
--| If at least one is found, return Found => TRUE, Result => <the digits>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Number( --| Scan sequence of digits
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff one or more digits found
Result : out integer; --| Number scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a sequence of digits.
--| If at least one is found, return Found => TRUE, Result => <the digits>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| Modifies: Raises, Modifies, Errors
pragma Page;
function Is_Signed_Number( --| Check if Scanner is at a decimal digit or
--| sign (+/-)
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff Scan_Signed_Number would return a non-null
--| string.
--| N/A: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Signed_Number( --| Scan signed sequence of digits
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff one or more digits found
Result : out String_Type;--| Number scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a sequence of digits preceeded with optional sign.
--| If at least one digit is found, return Found => TRUE,
--| Result => <the digits>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Signed_Number( --| Scan signed sequence of digits
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff one or more digits found
Result : out integer; --| Number scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a sequence of digits preceeded with optional sign.
--| If at least one digit is found, return Found => TRUE,
--| Result => <the digits>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| Modifies: Raises, Modifies, Errors
pragma Page;
function Is_Space( --| Check if T is at a space or tab
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff Scan_Space would return a non-null string.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Space( --| Scan sequence of white space characters
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff space found
Result : out String_Type --| Spaces scanned from string
);
--| Effects: Scan T past all white space (spaces
--| and tabs. If at least one is found, return Found => TRUE,
--| Result => <the characters>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Skip_Space( --| Skip white space
T : in Scanner --| String to be scanned
);
--| Effects: Scan T past all white space (spaces and tabs).
--| Modifies: Raises, Modifies, Errors
pragma Page;
function Is_Ada_Id( --| Check if T is at an Ada identifier
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff Scan_Ada_Id would return a non-null string.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Ada_Id( --| Scan Ada identifier
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff an Ada identifier found
Result : out String_Type;--| Identifier scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a valid Ada identifier.
--| If one is found, return Found => TRUE, Result => <the characters>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| Modifies: Raises, Modifies, Errors
pragma Page;
function Is_Quoted( --| Check if T is at a double quote
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff T is at a quoted string (eg. ... "Hello" ...).
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Quoted( --| Scan a quoted string
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff a quoted string found
Result : out String_Type;--| Quoted string scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan at T for an opening quote
--| followed by a sequence of characters and ending with a closing
--| quote. If successful, return Found => TRUE, Result => <the characters>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| A pair of quotes within the quoted string is converted to a single quote.
--| The outer quotes are stripped.
--| Modifies: Raises, Modifies, Errors
pragma Page;
function Is_Enclosed( --| Check if T is at an enclosing character
B : in character; --| Enclosing open character
E : in character; --| Enclosing close character
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff T as encosed by B and E (eg. ... [ABC] ...).
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Enclosed( --| Scan an enclosed string
B : in character; --| Enclosing open character
E : in character; --| Enclosing close character
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff a quoted string found
Result : out String_Type;--| Quoted string scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan at T for an enclosing character
--| followed by a sequence of characters and ending with an enclosing character.
--| If successful, return Found => TRUE, Result => <the characters>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| The enclosing characters are stripped.
--| Modifies: Raises, Modifies, Errors
pragma Page;
function Is_Sequence( --| Check if T is at some sequence characters
Chars : in String_Type; --| Characters to be scanned
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff T is at some character of Chars.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
function Is_Sequence( --| Check if T is at some sequence characters
Chars : in string; --| Characters to be scanned
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff T is at some character of Chars.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Sequence( --| Scan arbitrary sequence of characters
Chars : in String_Type;--| Characters that should be scanned
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff a sequence found
Result : out String_Type;--| Sequence scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a sequence of characters C such that C appears in
--| Char. If at least one is found, return Found => TRUE,
--| Result => <the characters>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| Modifies: Raises, Modifies, Errors
--| Notes:
--| Scan_Sequence("0123456789", S, Index, Found, Result)
--| is equivalent to Scan_Number(S, Index, Found, Result)
--| but is less efficient.
----------------------------------------------------------------
procedure Scan_Sequence( --| Scan arbitrary sequence of characters
Chars : in string; --| Characters that should be scanned
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff a sequence found
Result : out String_Type;--| Sequence scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a sequence of characters C such that C appears in
--| Char. If at least one is found, return Found => TRUE,
--| Result => <the characters>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| Modifies: Raises, Modifies, Errors
--| Notes:
--| Scan_Sequence("0123456789", S, Index, Found, Result)
--| is equivalent to Scan_Number(S, Index, Found, Result)
--| but is less efficient.
pragma Page;
function Is_Not_Sequence( --| Check if T is not at some seuqnce of character
Chars : in String_Type; --| Characters to be scanned
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff T is not at some character of Chars.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
function Is_Not_Sequence( --| Check if T is at some sequence of characters
Chars : in string; --| Characters to be scanned
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff T is not at some character of Chars.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Not_Sequence( --| Scan arbitrary sequence of characters
Chars : in String_Type;--| Characters that should be scanned
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff a sequence found
Result : out String_Type;--| Sequence scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a sequence of characters C such that C does not appear
--| in Chars. If at least one such C is found, return Found => TRUE,
--| Result => <the characters>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Not_Sequence( --| Scan arbitrary sequence of characters
Chars : in string; --| Characters that should be scanned
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff a sequence found
Result : out String_Type;--| Sequence scanned from string
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a sequence of characters C such that C does not appear
--| in Chars. If at least one such C is found, return Found => TRUE,
--| Result => <the characters>.
--| Otherwise return Found => FALSE and Result is unpredictable.
--| Modifies: Raises, Modifies, Errors
pragma Page;
function Is_Literal( --| Check if T is at literal Chars
Chars : in String_Type; --| Characters to be scanned
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff T is at literal Chars.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
function Is_Literal( --| Check if T is at literal Chars
Chars : in string; --| Characters to be scanned
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff T is at literal Chars.
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Literal( --| Scan arbitrary literal
Chars : in String_Type;--| Literal that should be scanned
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff a sequence found
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a litral Chars such that Char matches the sequence
--| of characters in T. If found, return Found => TRUE,
--| Otherwise return Found => FALSE
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Literal( --| Scan arbitrary literal
Chars : in string; --| Literal that should be scanned
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff a sequence found
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a litral Chars such that Char matches the sequence
--| of characters in T. If found, return Found => TRUE,
--| Otherwise return Found => FALSE
--| Modifies: Raises, Modifies, Errors
pragma Page;
function Is_Not_Literal( --| Check if T is not at literal Chars
Chars : in string; --| Characters to be scanned
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff T is not at literal Chars
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
function Is_Not_Literal( --| Check if T is not at literal Chars
Chars : in String_Type; --| Characters to be scanned
T : in Scanner --| The string being scanned
) return boolean;
--| Effects: Return TRUE iff T is not at literal Chars
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Not_Literal( --| Scan arbitrary literal
Chars : in string; --| Literal that should be scanned
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff a sequence found
Result : out String_Type;--| String up to literal
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a litral Chars such that Char does not match the
--| sequence of characters in T. If found, return Found => TRUE,
--| Otherwise return Found => FALSE
--| Modifies: Raises, Modifies, Errors
----------------------------------------------------------------
procedure Scan_Not_Literal( --| Scan arbitrary literal
Chars : in String_Type;--| Literal that should be scanned
T : in Scanner; --| String to be scanned
Found : out boolean; --| TRUE iff a sequence found
Result : out String_Type;--| String up to literal
Skip : in boolean := false
--| Skip white spaces before scan
);
--| Effects: Scan T for a litral Chars such that Char does not match the
--| sequence of characters in T. If found, return Found => TRUE,
--| Otherwise return Found => FALSE
--| Modifies: Raises, Modifies, Errors
pragma Page;
private
pragma List(off);
type Scan_Record is
record
text : String_Type; --| Copy of string being scanned
index : positive := 1; --| Current position of Scanner
mark : natural := 0; --| Mark
end record;
type Scanner is access Scan_Record;
pragma List(on);
end String_Scanner;
pragma Page;
-- 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 : symbol_info.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:37:08
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxsymbol_info.ada
-- $Header: symbol_info.a,v 0.1 86/04/01 15:13:15 ada Exp $
-- $Log: symbol_info.a,v $
-- Revision 0.1 86/04/01 15:13:15 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:42:36 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 Symbol_Table, Rule_Table;
use Symbol_Table, Rule_Table;
package Symbol_Info is
--
-- The following array declarations are used to compute the
-- the rules that have a particular symbol on the left hand
-- side. NONTERMINAL_YIELD contains the rules and
-- NONTERMINAL_YIELD_OFFSET contains the offset into the first array
-- indexed by a particular nonterminal. The user of this package
-- should not attempt to alter the contents of these arrays. They
-- are visible in the spec only for efficiency reasons.
--
type Yield_Index is new Integer;
type Rule_Array is array (Yield_Index range <>) of Rule;
type Offset_Array is array (Grammar_Symbol range <>) of Yield_Index;
type Rule_Array_Pointer is access Rule_Array;
type Offset_Array_Pointer is access Offset_Array;
Nonterminal_Yield : Rule_Array_Pointer;
Nonterminal_Yield_Index : Offset_Array_Pointer;
---
procedure Initialize;
function Is_Nullable(Sym: Grammar_Symbol) return Boolean;
Undefined_Nonterminal : exception;
-- raised if a nonterminal doesn't appear on left hand side of
-- any rule.
--RJS pragma inline(is_nullable);
end Symbol_Info;
-- 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 : symbol_info_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:37:23
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxsymbol_info_body.ada
-- $Header: symbol_info_body.a,v 0.1 86/04/01 15:13:25 ada Exp $
-- $Log: symbol_info_body.a,v $
-- Revision 0.1 86/04/01 15:13:25 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:46:56 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 Text_IO;
package body Symbol_Info is
SCCS_ID : constant String := "@(#) symbol_info_body.ada, Version 1.2";
Rcs_ID : constant String := "$Header: symbol_info_body.a,v 0.1 86/04/01 15:13:25 ada Exp $";
type Nullables_Array is array (Grammar_Symbol range <>) of Boolean;
type Nullables_Array_Pointer is access Nullables_Array;
Nullables : Nullables_Array_Pointer;
--
-- initializes the elements of the array pointed to by
-- NULLABLES to false if they cannot derive the empty
-- string and TRUE if they can derive the empty string.
--
procedure Find_Nullables is
Sym_Position : Natural;
Nonterminal_Sym : Grammar_Symbol;
RHS_Sym : Grammar_Symbol;
No_More_Added : Boolean;
Rule_Length : Natural;
begin
--& Verdix 4.06 bug
--& nullables.all := (nullables.all'range => false);
--& bug fix
for S in Nullables.all'range loop
Nullables(S) := False;
end loop;
--& end bug fix
-- First determine the symbols that are trivially nullable.
for R in First_Rule..Last_Rule loop
if Length_of(R) = 0 then
Nullables(Get_LHS(R)) := True;
end if;
end loop;
loop
No_More_Added := True;
for R in First_Rule..Last_Rule loop
Nonterminal_Sym := Get_LHS(R);
if not Nullables(Nonterminal_Sym) then
Sym_Position := 1;
Rule_Length := Length_of(R);
while Sym_Position <= Rule_Length loop
RHS_Sym := Get_RHS(R, Sym_Position);
exit when Is_Terminal(RHS_Sym) or else
not Nullables(RHS_Sym);
Sym_Position := Sym_Position + 1;
end loop;
if Sym_Position > Rule_Length then
Nullables(Nonterminal_Sym) := True;
No_More_Added := False;
end if;
end if;
end loop;
exit when No_More_Added;
end loop;
end Find_Nullables;
function Is_Nullable(Sym: Grammar_Symbol) return Boolean is
begin
return Nullables(Sym);
end Is_Nullable;
procedure Make_Rules_Null_Position is
Null_Position : Integer;
RHS_Sym : Grammar_Symbol;
begin
for R in First_Rule..Last_Rule loop
Null_Position := Length_of(R);
while Null_Position /= 0 loop
RHS_Sym := Get_RHS(R, Null_Position);
if Is_Terminal(RHS_Sym) or else not Nullables(RHS_Sym) then
exit;
end if;
Null_Position := Null_Position - 1;
end loop;
Set_Null_Pos(R, Null_Position);
end loop;
end Make_Rules_Null_Position;
procedure Find_Rule_Yields is
use Text_IO; -- To report undefined nonterminals
Found_Undefined_Nonterminal: Boolean := False;
Current_Index : Yield_Index;
begin
-- First initialize the arrays to the correct size --
Nonterminal_Yield := new Rule_Array
(Yield_Index(First_Rule)..Yield_Index(Last_Rule));
Nonterminal_Yield_Index := new Offset_Array
(First_Symbol(Nonterminal)..Last_Symbol(Nonterminal) + 1);
Current_Index := Yield_Index(First_Rule);
for Sym in First_Symbol(Nonterminal)..Last_Symbol(Nonterminal) loop
Nonterminal_Yield_Index(Sym) := Current_Index;
for R in First_Rule..Last_Rule loop
if Get_LHS(R) = Sym then
Nonterminal_Yield(Current_Index) := R;
Current_Index := Current_Index + 1;
end if;
end loop;
if Nonterminal_Yield_Index(Sym) = Current_Index then
Found_Undefined_Nonterminal := True;
Put_Line ("Ayacc: Nonterminal " & Get_Symbol_Name(Sym) &
" does not appear on the " &
"left hand side of any rule.");
end if;
end loop;
Nonterminal_Yield_Index(Last_Symbol(Nonterminal) + 1) := Current_Index;
-- So you can easily determine the end of the list in loops
-- bye comparing the index to the index of sym+1.
if Found_Undefined_Nonterminal then
raise Undefined_Nonterminal;
end if;
end Find_Rule_Yields;
-- First detect nonterminals that can't be derived from the start symbol.
-- Then detect nonterminals that don't derive any token string.
--
-- NOTE: We should use Digraph to do this stuff when we
-- have time to put it in.
procedure Check_Grammar is
use Text_IO; -- to report errors
type Nonterminal_Array is array (Grammar_Symbol range <>) of Boolean;
Ok : Nonterminal_Array
(First_Symbol(Nonterminal)..Last_Symbol(Nonterminal));
More : Boolean;
I : Natural;
Rule_Length : Natural;
Found_Error : Boolean := False;
RHS_Sym, LHS_Sym: Grammar_Symbol;
Bad_Grammar : exception; -- Move this somewhere else!!!
begin
-- check if each nonterminal is deriveable from the start symbol --
-- To be added! We should use digraph for this
-- check if each nonterminal can derive a terminal string. --
--& Verdix 4.06 bug
--& ok := (ok'range => false);
--& bug fix
for S in Ok'range loop
Ok(S) := False;
end loop;
--& end bug fix
More := True;
while More loop
More := False;
for R in First_Rule..Last_Rule loop
LHS_Sym := Get_LHS(R);
if not Ok(LHS_Sym) then
I := 1;
Rule_Length := Length_of(R);
while I <= Rule_Length loop
RHS_Sym := Get_RHS(R, I);
if Is_Nonterminal(RHS_Sym) and then
not Ok(RHS_Sym)
then
exit;
end if;
I := I + 1;
end loop;
if I > Rule_Length then -- nonterminal can derive terminals
Ok(LHS_Sym) := True;
More := True;
end if;
end if;
end loop;
end loop;
for J in Ok'range loop
if not Ok(J) then
Put_Line ("Ayacc: Nonterminal " & Get_Symbol_Name(J) &
" does not derive a terminal string");
Found_Error := True;
end if;
end loop;
if Found_Error then
raise Bad_Grammar;
end if;
end Check_Grammar;
procedure Initialize is
begin
Nullables := new Nullables_Array
(First_Symbol(Nonterminal) .. Last_Symbol(Nonterminal));
Find_Rule_Yields;
Check_Grammar;
Find_Nullables;
Make_Rules_Null_Position;
end Initialize;
end Symbol_Info;
-- 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 : symbol_table.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:37:38
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxsymbol_table.ada
-- $Header: symbol_table.a,v 0.1 86/04/01 15:13:41 ada Exp $
-- $Log: symbol_table.a,v $
-- Revision 0.1 86/04/01 15:13:41 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:47:05 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.
--
package Symbol_Table is
type Symbol_Type is (Start, Nonterminal, Terminal);
type Grammar_Symbol is range -5_000..5_000;
type Precedence is range 0..5_000;
type Associativity is (Left_Associative, Right_Associative,
Nonassociative, Undefined);
function Insert_Identifier(Name: in String) return Grammar_Symbol;
function Insert_Terminal (Name: String;
Prec: Precedence := 0;
Assoc: Associativity := Undefined)
return Grammar_Symbol;
function Get_Associativity(ID: Grammar_Symbol) return Associativity;
function Get_Precedence (ID: Grammar_Symbol) return Precedence;
function Get_Symbol_Name (ID: Grammar_Symbol) return String;
function First_Symbol (Kind: Symbol_Type) return Grammar_Symbol;
function Last_Symbol (Kind: Symbol_Type) return Grammar_Symbol;
function Start_Symbol return Grammar_Symbol;
function End_Symbol return Grammar_Symbol;
function Is_Terminal (ID: Grammar_Symbol) return Boolean;
function Is_Nonterminal (ID: Grammar_Symbol) return Boolean;
Illegal_Entry, Redefined_Precedence_Error : exception;
--RJS pragma inline(is_terminal, is_nonterminal);
end Symbol_Table;
-- 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 : symbol_table_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:37:53
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxsymbol_table_body.ada
-- $Header: symbol_table_body.a,v 0.1 86/04/01 15:13:55 ada Exp $
-- $Log: symbol_table_body.a,v $
-- Revision 0.1 86/04/01 15:13:55 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:02 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.
--
package body Symbol_Table is
SCCS_ID : constant String := "@(#) symbol_table_body.ada, Version 1.2";
Next_Free_Terminal : Grammar_Symbol := 0;
Next_Free_Nonterminal : Grammar_Symbol := -1;
Start_Symbol_Pos, End_Symbol_Pos : Grammar_Symbol;
type String_Pointer is access String;
type Table_Entry(ID : Grammar_Symbol);
type Entry_Pointer is access Table_Entry;
type Table_Entry(ID :Grammar_Symbol) is
record
Name : String_Pointer;
Next : Entry_Pointer;
case ID is
when 0..Grammar_Symbol'Last => -- Terminal
Prec : Precedence;
Assoc : Associativity;
when others => -- Nonterminal
null;
end case;
end record;
Hash_Table_Size : constant := 613; -- A large prime number
type Hash_Index is range 0..Hash_Table_Size-1;
Hash_Table : array(Hash_Index) of Entry_Pointer;
--
-- Create a 'dynamic' array for looking up an entry
-- for a given grammar_symbol.
--
Block_Size : constant Grammar_Symbol := 100;
type Lookup_Array is
array(Grammar_Symbol range 0..Block_Size-1) of Entry_Pointer;
type Block;
type Block_Pointer is access Block;
type Block is
record
Lookup : Lookup_Array;
Next : Block_Pointer := null;
end record;
-- have separate blocks for terminals and nonterminals.
Terminal_Blocks, Nonterminal_Blocks : Block_Pointer := new Block;
procedure Make_Lookup_Table_Entry
(ID : in Grammar_Symbol;
Entry_Ptr : in Entry_Pointer) is
ID_Block : Block_Pointer;
Block_Number : Integer;
begin
if ID >= 0 then
ID_Block := Terminal_Blocks;
else
ID_Block := Nonterminal_Blocks;
end if;
Block_Number := Integer (abs ID / Block_Size);
for I in 1..Block_Number loop
if ID_Block.Next = null then
ID_Block.Next := new Block;
end if;
ID_Block := ID_Block.Next;
end loop;
ID_Block.Lookup((abs ID) mod Block_Size) := Entry_Ptr;
end Make_Lookup_Table_Entry;
function Get_Lookup_Table_Entry(ID: Grammar_Symbol) return Entry_Pointer is
ID_Block : Block_Pointer;
begin
if ID >= 0 then
ID_Block := Terminal_Blocks;
else
ID_Block := Nonterminal_Blocks;
end if;
for I in 1.. abs ID / Block_Size loop
ID_Block := ID_Block.Next;
end loop;
return ID_Block.Lookup((abs ID) mod Block_Size);
end Get_Lookup_Table_Entry;
-- some day someone should put in a good hash function.
function Hash_Value (S : String) return Hash_Index is
H : Integer;
Mid : Integer;
begin
Mid := (S'First + S'Last) / 2;
H := ((Character'Pos(S(S'First)) +
Character'Pos(S(Mid)) +
Character'Pos(S(S'Last)))
* S'Length * 16 ) mod Hash_Table_Size;
return Hash_Index(H);
end Hash_Value;
function Insert_Identifier (Name: in String) return Grammar_Symbol is
Index : Hash_Index;
Entry_Ptr : Entry_Pointer;
begin
Index := Hash_Value(Name);
Entry_Ptr := Hash_Table(Index);
if Entry_Ptr = null then
Entry_Ptr := new Table_Entry(Next_Free_Nonterminal);
Entry_Ptr.Name := new String(1..Name'Length);
Entry_Ptr.Name.all := Name;
Hash_Table(Index) := Entry_Ptr;
Make_Lookup_Table_Entry(Next_Free_Nonterminal, Entry_Ptr);
Next_Free_Nonterminal := Next_Free_Nonterminal - 1;
else
loop
if Entry_Ptr.Name.all = Name then
return Entry_Ptr.ID;
end if;
if Entry_Ptr.Next = null then
exit;
end if;
Entry_Ptr := Entry_Ptr.Next;
end loop;
Entry_Ptr.Next := new Table_Entry(Next_Free_Nonterminal);
Entry_Ptr := Entry_Ptr.Next;
Entry_Ptr.Name := new String(1..Name'Length);
Entry_Ptr.Name.all := Name;
Make_Lookup_Table_Entry(Next_Free_Nonterminal, Entry_Ptr);
Next_Free_Nonterminal := Next_Free_Nonterminal - 1;
end if;
return Next_Free_Nonterminal + 1;
end Insert_Identifier;
function Insert_Terminal
(Name : String;
Prec : Precedence := 0;
Assoc : Associativity := Undefined) return Grammar_Symbol is
Index : Hash_Index;
Entry_Ptr : Entry_Pointer;
begin
Index := Hash_Value(Name);
Entry_Ptr := Hash_Table(Index);
if Entry_Ptr = null then
Entry_Ptr := new Table_Entry(Next_Free_Terminal);
Entry_Ptr.Name := new String(1..Name'Length);
Entry_Ptr.Name.all := Name;
Entry_Ptr.Assoc := Assoc;
Entry_Ptr.Prec := Prec;
Hash_Table(Index) := Entry_Ptr;
Make_Lookup_Table_Entry(Next_Free_Terminal, Entry_Ptr);
Next_Free_Terminal := Next_Free_Terminal + 1;
else
loop
if Entry_Ptr.Name.all = Name then
if Entry_Ptr.ID < 0 then -- Look out for nonterminals
raise Illegal_Entry;
end if;
if Prec /= 0 then
if Entry_Ptr.Prec /= 0 then
raise Redefined_Precedence_Error;
end if;
Entry_Ptr.Prec := Prec;
Entry_Ptr.Assoc := Assoc;
end if;
return Entry_Ptr.ID;
end if;
if Entry_Ptr.Next = null then
exit;
end if;
Entry_Ptr := Entry_Ptr.Next;
end loop;
Entry_Ptr.Next := new Table_Entry(Next_Free_Terminal);
Entry_Ptr := Entry_Ptr.Next;
Entry_Ptr.Name := new String(1..Name'Length);
Entry_Ptr.Name.all := Name;
Entry_Ptr.Assoc := Assoc;
Entry_Ptr.Prec := Prec;
Make_Lookup_Table_Entry(Next_Free_Terminal, Entry_Ptr);
Next_Free_Terminal := Next_Free_Terminal + 1;
end if;
return Next_Free_Terminal - 1;
end Insert_Terminal;
function Get_Associativity (ID: Grammar_Symbol) return Associativity is
begin
return Get_Lookup_Table_Entry(ID).Assoc;
end;
function Get_Precedence (ID: Grammar_Symbol) return Precedence is
begin
return Get_Lookup_Table_Entry(ID).Prec;
end;
function Get_Symbol_Name (ID: Grammar_Symbol) return String is
begin
return Get_Lookup_Table_Entry(ID).Name.all;
end;
function First_Symbol (Kind: Symbol_Type) return Grammar_Symbol is
begin
if Kind = Terminal then
return 0;
else
return Next_Free_Nonterminal + 1;
end if;
end;
function Last_Symbol (Kind: Symbol_Type) return Grammar_Symbol is
begin
if Kind = Terminal then
return Next_Free_Terminal - 1;
else
return -1;
end if;
end;
function First_Terminal return Grammar_Symbol is
begin
return 0;
end;
function Last_Terminal return Grammar_Symbol is
begin
return Next_Free_Terminal - 1;
end;
function Start_Symbol return Grammar_Symbol is
begin
return Start_Symbol_Pos;
end;
function End_Symbol return Grammar_Symbol is
begin
return End_Symbol_Pos;
end;
function Is_Terminal (ID: Grammar_Symbol) return Boolean is
begin
return ID >= 0;
end;
function Is_Nonterminal (ID: Grammar_Symbol) return Boolean is
begin
return ID < 0;
end;
begin
End_Symbol_Pos := Insert_Terminal("END_OF_INPUT");
Start_Symbol_Pos := Insert_Identifier("$accept");
-- declare a dummy symbol to insert the "error" token.
declare
Dummy_Sym : Grammar_Symbol;
begin
Dummy_Sym := Insert_Terminal("ERROR");
end;
end Symbol_Table;
-- 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.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:38:10
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxtokens_file.ada
-- $Header: tokens_file.a,v 0.1 86/04/01 15:14:22 ada Exp $
-- $Log: tokens_file.a,v $
-- Revision 0.1 86/04/01 15:14:22 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:11 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.
--
package Tokens_File is
procedure Open;
procedure Start_Tokens_Package;
function Tokens_Package_Header_Has_Been_Generated return Boolean;
--| Returns: True iff Start_Tokens_Package has been called.
procedure Complete_Tokens_Package;
procedure Make_C_Lex_Package; -- yylex that interfaces to C!!!
-- Creates the #define also!!
procedure Close;
procedure Write (S : in String);
procedure Writeln(S: in String);
end Tokens_File;
-- 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: tokens_file_body.a,v 0.1 86/04/01 15:14:29 ada Exp $
-- $Log: tokens_file_body.a,v $
-- 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 File_Names, Source_File, Symbol_Table, Text_IO;
with String_Pkg;
package body Tokens_File is
SCCS_ID : constant String := "@(#) tokens_file_body.ada, Version 1.2";
Rcs_ID : constant String := "$Header: tokens_file_body.a,v 0.1 86/04/01 15:14:29 ada Exp $";
Package_Header_Generated : Boolean := False;
T_File: Text_IO.File_Type;
procedure Open is
use Text_IO;
begin
Create(T_File, Out_File, File_Names.Get_Tokens_File_Name);
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
Writeln("package " & 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
Tokens_On_Line: Natural := 1;
use String_Pkg;
use Symbol_Table;
begin
if not Package_Header_Generated then
Start_Tokens_Package;
end if;
Writeln(" YYLVal, YYVal : YYSType; ");
Writeln(" type Token is");
Write(" (");
for I in First_Symbol(Terminal)..Last_Symbol(Terminal)-1 loop
if Tokens_On_Line = 4 then
Write(Value (Mixed (Get_Symbol_Name(I))));
Writeln(",");
Write(" ");
Tokens_On_Line := 1;
else
Write(Value (Mixed (Get_Symbol_Name(I))));
Write(", ");
end if;
Tokens_On_Line := Tokens_On_Line + 1;
end loop;
Write(Value (Mixed (Get_Symbol_Name(Last_Symbol(Terminal)))));
Writeln(" );");
Writeln("");
Writeln(" Syntax_Error : exception;");
Writeln("");
Writeln("end " & 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;
begin
Create(The_Ada_File, Out_File, File_Names.Get_C_Lex_File_Name);
Put_Line(The_Ada_File, "with " & File_Names.Tokens_Unit_Name &
"; use " & File_Names.Tokens_Unit_Name & ";");
Put_Line(The_Ada_File, "package " & File_Names.C_Lex_Unit_Name & " is");
Put_Line(The_Ada_File, " function YYLex return Token;");
Put_Line(The_Ada_File, "end " & File_Names.C_Lex_Unit_Name & ";");
New_Line(The_Ada_File);
New_Line(The_Ada_File);
Put_Line(The_Ada_File, "package body " & 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, File_Names.Get_Include_File_Name);
Put_Line(The_Define_File, "/* C_Lex Token Definition for type " &
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 " & File_Names.C_Lex_Unit_Name & ";");
Close(The_Ada_File);
Close(The_Define_File);
end;
end Tokens_File;
-- 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 : verbose_file.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:38:37
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxverbose_file.ada
-- $Header: verbose_file.a,v 0.1 86/04/01 15:14:39 ada Exp $
-- $Log: verbose_file.a,v $
-- Revision 0.1 86/04/01 15:14:39 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:29 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 Symbol_Table, Rule_Table, LR0_Machine;
use Symbol_Table, Rule_Table, LR0_Machine;
package Verbose_File is
procedure Open;
procedure Close;
procedure Write (Ch : in Character);
procedure Write (S : in String);
procedure Write_Line (S : in String := "");
procedure Print_Item (Item_1 : in Item);
procedure Print_Item_Set (Set_1 : in Item_Set);
procedure Print_Grammar_Symbol (Sym: in Grammar_Symbol);
procedure Print_Rule (R : in Rule);
end Verbose_File;
-- 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 : verbose_file_body.ada
-- Component of : ayacc
-- Version : 1.2
-- Date : 11/21/86 12:38:50
-- SCCS File : disk21~/rschm/hasee/sccs/ayacc/sccs/sxverbose_file_body.ada
-- $Header: verbose_file_body.a,v 0.1 86/04/01 15:14:46 ada Exp $
-- $Log: verbose_file_body.a,v $
-- Revision 0.1 86/04/01 15:14:46 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:37 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 Text_IO, File_Names;
use Text_IO;
package body Verbose_File is
SCCS_ID : constant String := "@(#) verbose_file_body.ada, Version 1.2";
Rcs_ID : constant String := "$Header: verbose_file_body.a,v 0.1 86/04/01 15:14:46 ada Exp $";
V_File : File_Type; -- The verbose file
procedure Open is
use File_Names;
begin
Create(V_File, Out_File, Get_Verbose_File_Name);
end Open;
procedure Close is
begin
Close(V_File);
end Close;
procedure Write(Ch : in Character) is
begin
Put(V_File, Ch);
end Write;
procedure Write(S : in String) is
begin
Put(V_File, S);
end Write;
procedure Write_Line(S : in String := "") is
begin
Put_Line(V_File, S);
end Write_Line;
procedure Print_Grammar_Symbol(Sym: in Grammar_Symbol) is
begin
Put(V_File, Get_Symbol_Name(Sym));
end;
procedure Print_Item(Item_1 : in Item) is
begin
Put(V_File, "(" & Rule'Image(Item_1.Rule_ID) & ") ");
Put(V_File, Get_Symbol_Name(Get_LHS(Item_1.Rule_ID)) & Ascii.Ht & ": ");
if Item_1.Dot_Position = 0 then
Put(V_File, "_ ");
end if;
for I in 1..Length_of(Item_1.Rule_ID) loop
Put(V_File, Get_Symbol_Name(Get_RHS(Item_1.Rule_ID, I)));
Put(V_File, " ");
if I = Item_1.Dot_Position then
Put(V_File, "_ ");
end if;
end loop;
end Print_Item;
procedure Print_Item_Set(Set_1: in Item_Set) is
use Item_Set_Pack;
Iterator : Item_Iterator;
Temp_Item : Item;
begin
Initialize(Iterator, Set_1);
while More(Iterator) loop
Next(Iterator, Temp_Item);
Print_Item(Temp_Item);
New_Line(V_File);
end loop;
end Print_Item_Set;
procedure Print_Rule(R : in Rule) is
begin
Put(V_File, "(" & Rule'Image(R) & ") ");
Put(V_File, Get_Symbol_Name(Get_LHS(R)) & Ascii.Ht & ": ");
for I in 1..Length_of(R) loop
Put(V_File, Get_Symbol_Name(Get_RHS(R, I)));
Put(V_File, " ");
end loop;
end Print_Rule;
end Verbose_File;