|
|
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: B T
Length: 27249 (0x6a71)
Types: TextFile
Names: »B«
└─⟦afbc8121e⟧ Bits:30000532 8mm tape, Rational 1000, MC68020_OS2000 7_2_2
└─⟦77aa8350c⟧ »DATA«
└─⟦f794ecd1d⟧
└─⟦4c85d69e2⟧
└─⟦this⟧
-- The use of this system is subject to the software license terms and
-- conditions agreed upon between Rational and the Customer.
--
-- Copyright 1988 by Rational.
--
-- RESTRICTED RIGHTS LEGEND
--
-- Use, duplication, or disclosure by the Government is subject to
-- restrictions as set forth in subdivision (b)(3)(ii) of the Rights in
-- Technical Data and Computer Software clause at 52.227-7013.
--
--
-- Rational
-- 3320 Scott Boulevard
-- Santa Clara, California 95054-3197
--
-- PROPRIETARY AND CONFIDENTIAL INFORMATION OF RATIONAL;
-- USE OR COPYING WITHOUT EXPRESS WRITTEN AUTHORIZATION
-- IS STRICTLY PROHIBITED. THIS MATERIAL IS PROTECTED AS
-- AN UNPUBLISHED WORK UNDER THE U.S. COPYRIGHT ACT OF
-- 1976. CREATED 1988. ALL RIGHTS RESERVED.
--
--
with Primitive_Io; -- For debugging only
package body Literal_Parser is
-- procedure Trace
-- (S : String;
-- Absorb_Output : Boolean := Primitive_Io.Global_Absorb_Output)
-- renames Primitive_Io.Put_Line;
-- Should these constants be here???
Line_Terminator : constant Character := Ascii.Cr;
--*** Line_Terminator : constant Character := Ascii.Lf;
Page_Terminator : constant Character := Ascii.Ff;
-- u
-- +-----------\
-- | \ D
-- . v d \ / e
-- +----------> 10 ---------> 11* -----------------------+
-- B | | D
-- | d | # x . x # e v d |
-- 1 -----> 2 -----> 3 -----> 4 -----> 5 -----> 6 -----> 7* ----> 8 -----> 9*
-- |s / ^ \ ^ / \ ^ / \ | / ^
-- | u/ | D | u / D | u / X s| u / |
-- v / | +------ +------ | / |
-- +<--- | v / |
-- | | +<-- |
-- v d | | |
-- 12 ------+ v d |
-- 13 -------+
-- The diagram above defines a finite state machine to recognize Ada real
-- constants in TEXT_IO. There are 13 states, numbered 1-13. The start state
-- is 1; accept states are marked with an asterisk. The characters that cause
-- state transitions are:
--
-- d,D a decimal digit, one of 0123456789
-- x,X an extended digit, either a decimal digit or a letter (either case)
-- u an underscore
-- s a sign, either + or -
-- # a pound sign or a colon
-- . a radix point
-- e either E or e
-- B a space, tab, line terminator, or page terminator
--
-- The letters D, B, and X are used to indicate self-loops, which are difficult
-- to draw in this medium. Pounds signs can be replaced with colons, but the
-- replacement must be uniform; you can't have one of each.
--
-- e
-- +------------------------------------+
-- B | | D
-- | d | # x # e v s d |
-- 1 ------> 2* -----> 3 ----> 4 ------> 5* ----> 6 -----> 7 -----> 8*
-- | / ^ \ ^ / \ | ^ /^
-- |s u/ | D | u / X | | u / |
-- | / | +------ | +------ |
-- v / | | d |
-- +<--- | +-----------------+
-- | |
-- v d |
-- 9 --------+
--
-- This diagram defines the syntax of an Ada integer literal. The same
-- conventions are used. The difference between an integer and real literal
-- is that a radix point is required in a real constant and forbidden in
-- an integer constant. Also, integer literals may not have negative
-- exponents, but that is considered by the AJPO Language Laywers to be a
-- "semantic restriction" that should not effect how things are parsed.
-- B X
-- | a | u
-- 1 ------> 2* -------> 3
-- | ^ |
-- |q | x |
-- | +-----------+
-- |
-- v g q
-- 4 ------> 5 ----------> 6*
-- The above is a machine to recognize enumeration literals, which are either
-- identifers or character literals. The new notation used is:
--
-- a an alphabetic (letter)
-- q a quote
-- g any graphic character
S01 : constant := 1;
S02 : constant := S01 + 2;
S03 : constant := S02 + 4;
S04 : constant := S03 + 4;
S05 : constant := S04 + 6;
S06 : constant := S05 + 4;
S07 : constant := S06 + 6;
S08 : constant := S07 + 1;
S09 : constant := S08 + 2;
S10 : constant := S09 + 2;
S11 : constant := S10 + 1;
S12 : constant := S11 + 3;
S13 : constant := S12 + 1;
Szz : constant := S13 + 1;
T01 : constant := Szz;
T02 : constant := T01 + 2;
T03 : constant := T02 + 4;
T04 : constant := T03 + 4;
T05 : constant := T04 + 6;
T06 : constant := T05 + 1;
T07 : constant := T06 + 2;
T08 : constant := T07 + 1;
T09 : constant := T08 + 2;
Tzz : constant := T09 + 1;
-- These constants are used to define the states of the three machines.
-- Notes that in each expression Xnn + mm, mm is the number of
-- different arcs coming out of state nn.
type State is range S01 .. Tzz - 1;
type Character_Class is (Upper_Case_Extended,-- Must be in this order
Lower_Case_Extended,--
Upper_Case_Letter, --
Lower_Case_Letter, --
Letter_E, --
Digit, -- End of must be in this order
Underscore,
Sign,
Pound,
Point,
Separator, Terminator, Irrelevant_Character);
subtype Alphabetic is Character_Class range Upper_Case_Extended .. Letter_E;
subtype Alphanumeric is Character_Class range Upper_Case_Extended .. Digit;
type Class_Map_Type is array (Character) of Character_Class;
Class_Map : constant Class_Map_Type :=
Class_Map_Type'('0' .. '9' => Digit,
'a' .. 'd' => Lower_Case_Extended,
'e' => Letter_E,
'f' => Lower_Case_Extended,
'g' .. 'z' => Lower_Case_Letter,
'A' .. 'D' => Upper_Case_Extended,
'E' => Letter_E,
'F' => Upper_Case_Extended,
'G' .. 'Z' => Upper_Case_Letter,
'#' | ':' => Pound,
'+' | '-' => Sign,
'_' => Underscore,
'.' => Point,
' ' | Ascii.Ht => Separator,
Line_Terminator | Page_Terminator => Terminator,
others => Irrelevant_Character);
-- The state table consists of triples:
-- If_Class_Is: Character_Class;
-- Then_New_State_Is: State;
-- Last_Rule: Boolean;
If_Class_Is : constant array (State) of Character_Class :=
-- The machine to recognize Real Literals
(S01 + 0 => Digit,
S01 + 1 => Sign,
S02 + 0 => Digit,
S02 + 1 => Point,
S02 + 2 => Pound,
S02 + 3 => Underscore,
S03 + 0 => Digit,
S03 + 1 => Upper_Case_Extended,
S03 + 2 => Lower_Case_Extended,
S03 + 3 => Letter_E,
S04 + 0 => Digit,
S04 + 1 => Upper_Case_Extended,
S04 + 2 => Lower_Case_Extended,
S04 + 3 => Letter_E,
S04 + 4 => Point,
S04 + 5 => Underscore,
S05 + 0 => Digit,
S05 + 1 => Upper_Case_Extended,
S05 + 2 => Lower_Case_Extended,
S05 + 3 => Letter_E,
S06 + 0 => Digit,
S06 + 1 => Upper_Case_Extended,
S06 + 2 => Lower_Case_Extended,
S06 + 3 => Letter_E,
S06 + 4 => Pound,
S06 + 5 => Underscore,
S07 + 0 => Letter_E,
S08 + 0 => Digit,
S08 + 1 => Sign,
S09 + 0 => Digit,
S09 + 1 => Underscore,
S10 + 0 => Digit,
S11 + 0 => Digit,
S11 + 1 => Letter_E,
S11 + 2 => Underscore,
S12 + 0 => Digit,
S13 + 0 => Digit,
-- The Machine that recognizes an Integer
T01 + 0 => Digit,
T01 + 1 => Sign,
T02 + 0 => Digit,
T02 + 1 => Letter_E,
T02 + 2 => Pound,
T02 + 3 => Underscore,
T03 + 0 => Digit,
T03 + 1 => Upper_Case_Extended,
T03 + 2 => Lower_Case_Extended,
T03 + 3 => Letter_E,
T04 + 0 => Digit,
T04 + 1 => Upper_Case_Extended,
T04 + 2 => Lower_Case_Extended,
T04 + 3 => Letter_E,
T04 + 4 => Pound,
T04 + 5 => Underscore,
T05 + 0 => Letter_E,
T06 + 0 => Digit,
T06 + 1 => Sign,
T07 + 0 => Digit,
T08 + 0 => Digit,
T08 + 1 => Underscore,
T09 + 0 => Digit);
Then_New_State_Is : constant array (State) of State :=
-- The machine to recognize Real Literals
(S01 + 0 => S02,
S01 + 1 => S12,
S02 + 0 => S02,
S02 + 1 => S10,
S02 + 2 => S03,
S02 + 3 => S12,
S03 + 0 => S04,
S03 + 1 => S04,
S03 + 2 => S04,
S03 + 3 => S04,
S04 + 0 => S04,
S04 + 1 => S04,
S04 + 2 => S04,
S04 + 3 => S04,
S04 + 4 => S05,
S04 + 5 => S03,
S05 + 0 => S06,
S05 + 1 => S06,
S05 + 2 => S06,
S05 + 3 => S06,
S06 + 0 => S06,
S06 + 1 => S06,
S06 + 2 => S06,
S06 + 3 => S06,
S06 + 4 => S07,
S06 + 5 => S05,
S07 + 0 => S08,
S08 + 0 => S09,
S08 + 1 => S13,
S09 + 0 => S09,
S09 + 1 => S13,
S10 + 0 => S11,
S11 + 0 => S11,
S11 + 1 => S08,
S11 + 2 => S10,
S12 + 0 => S02,
S13 + 0 => S09,
-- The Machine that recognizes an Integer
T01 + 0 => T02,
T01 + 1 => T09,
T02 + 0 => T02,
T02 + 1 => T06,
T02 + 2 => T03,
T02 + 3 => T09,
T03 + 0 => T04,
T03 + 1 => T04,
T03 + 2 => T04,
T03 + 3 => T04,
T04 + 0 => T04,
T04 + 1 => T04,
T04 + 2 => T04,
T04 + 3 => T04,
T04 + 4 => T05,
T04 + 5 => T03,
T05 + 0 => T06,
T06 + 0 => T08,
T06 + 1 => T07,
T07 + 0 => T08,
T08 + 0 => T08,
T08 + 1 => T07,
T09 + 0 => T02);
Last_Rule : constant array (State) of Boolean :=
-- The machine to recognize Real Literals
(S01 + 0 => False,
S01 + 1 => True,
S02 + 0 => False,
S02 + 1 => False,
S02 + 2 => False,
S02 + 3 => True,
S03 + 0 => False,
S03 + 1 => False,
S03 + 2 => False,
S03 + 3 => True,
S04 + 0 => False,
S04 + 1 => False,
S04 + 2 => False,
S04 + 3 => False,
S04 + 4 => False,
S04 + 5 => True,
S05 + 0 => False,
S05 + 1 => False,
S05 + 2 => False,
S05 + 3 => True,
S06 + 0 => False,
S06 + 1 => False,
S06 + 2 => False,
S06 + 3 => False,
S06 + 4 => False,
S06 + 5 => True,
S07 + 0 => True,
S08 + 0 => False,
S08 + 1 => True,
S09 + 0 => False,
S09 + 1 => True,
S10 + 0 => True,
S11 + 0 => False,
S11 + 1 => False,
S11 + 2 => True,
S12 + 0 => True,
S13 + 0 => True,
-- The Machine that recognizes an Integer
T01 + 0 => False,
T01 + 1 => True,
T02 + 0 => False,
T02 + 1 => False,
T02 + 2 => False,
T02 + 3 => True,
T03 + 0 => False,
T03 + 1 => False,
T03 + 2 => False,
T03 + 3 => True,
T04 + 0 => False,
T04 + 1 => False,
T04 + 2 => False,
T04 + 3 => False,
T04 + 4 => False,
T04 + 5 => True,
T05 + 0 => True,
T06 + 0 => False,
T06 + 1 => True,
T07 + 0 => True,
T08 + 0 => False,
T08 + 1 => True,
T09 + 0 => True);
-------------------------------------------------------------
procedure Parse_Numeric_Literal (Source : in String;
Integral : in Boolean;
Result : in out Numeric_Literal;
Status : out Parse_Status;
Last_Of_Source : out Natural) is
Source_First : Natural; -- Not Source'First, but 1st char of the numlit
Source_Index : Natural := Source'First;
Source_Last : constant Natural := Source'Last;
Current_State : State;
-- The state of the finite-state machine
Pound_Info : Character;
-- If we are between pound signs, Pound_Info contains the character
-- being used to represent a pound sign ('#' or ':'). If we are not
-- between pound signs, Pound_Info contains a blank.
Current_Char : Character;
Current_Class : Character_Class;
Rule : State;
-- These are work variables used to update the state
subtype Sign_Type is Numeric_Literals.Sign_Type;
Plus : constant Sign_Type := Numeric_Literals.Plus;
Minus : constant Sign_Type := Numeric_Literals.Minus;
Sign : Sign_Type;
-- Having parsed a numeric literal, put it away in the parameter
-- that the caller provided. The only problem is that the caller
-- may have provided too small of a place to put it. In that
-- case, an error status is returned, and Result.V is set so that
-- the caller knows how much space is needed and can allocate the
-- proper amount.
procedure Set_Result is
Result_Length : constant Integer := Source_Index - Source_First + 1;
begin
-- Trace ("Lp returning literal of length " &
-- Integer'Image (Result_Length));
-- Report the exact length required
Result.L := Result_Length;
if Result.Max_Length < Result_Length then
-- Trace ("Lp literal is too short");
Status := Numeric_Literal_Too_Short;
else
--Trace ("Lp literal is " &
-- Source (Source_First ..
-- Source_First + Result_Length - 1));
-- Result.V (1 .. Result_Length) :=
-- Source (Source_First .. Source_First + Result_Length - 1);
for I in 1 .. Result_Length loop
Result.V (I) := Source (Source_First + I - 1);
end loop;
Status := Ok;
end if;
end Set_Result;
begin
-- Trace ("Lp.Parse_Numeric_Literal from " & Source);
-- First, skip whitespace
-- Whitespace = blanks, tabs, line and page terminators
Last_Of_Source := Source_Last; -- anticipate all blanks or tabs
for I in Source'Range loop
if Class_Map (Source (I)) /= Separator then
if Class_Map (Source (I)) = Terminator then
Last_Of_Source := I - 1;
exit;
else
-- Found non-whitespace
Source_Index := I;
goto E1;
end if;
end if;
end loop;
-- If here, either source is empty or searched the entire string
-- and found nothing but whitespace
Status := Empty_Field;
-- Trace ("Lp empty field - 1");
return;
<<E1>> null;
-- Record the first character found of the numeric literal.
Source_First := Source_Index;
-- This will be the mantissa or the base, though right now we don't
-- know which. Assume not based as default.
Sign := Plus;
Result.Is_Based := False;
if Integral then
Current_State := T01;
else
Current_State := S01;
end if;
Pound_Info := ' ';
State_Machine:
loop
if Source_Index > Source_Last then
Current_Class := Irrelevant_Character;
exit State_Machine;
end if;
Current_Char := Source (Source_Index);
-- We don't increment Source_Index here because we haven't
-- yet decided that we want to "keep" the character.
Current_Class := Class_Map (Current_Char);
case Current_Class is
when Letter_E =>
-- The meaning of an E depends on whether it is between
-- pound signs. Either it is an extended digit or the
-- beginning of an exponent.
if Pound_Info = ' ' then
Sign := Plus;
-- This will be the exponent
end if;
when Pound =>
if Pound_Info = ' ' then
-- This is the first pound sign.
Pound_Info := Current_Char;
Sign := Plus;
elsif Pound_Info /= Current_Char then
-- Oops! We really shouldn't have considered this
-- character to be a pound sign, because it doesn't
-- match the first one. Treat it as if it were
-- something else.
Current_Class := Irrelevant_Character;
else
-- This is the second pound sign
Pound_Info := ' ';
Result.Is_Based := True;
end if;
when Literal_Parser.Sign =>
if Current_Char = '-' then
Sign := Minus;
-- The default value is Plus
end if;
when others =>
null;
end case;
Rule := Current_State;
Find_Rule:
loop
if If_Class_Is (Rule) = Current_Class then
Current_State := Then_New_State_Is (Rule);
exit Find_Rule;
elsif Last_Rule (Rule) then
exit State_Machine;
end if;
Rule := Rule + 1;
end loop Find_Rule;
-- If there is a transition for the current character and state,
-- then the character gets "read".
Source_Index := Source_Index + 1;
end loop State_Machine;
-- Let Source_Index point to the last character of the numlit now.
Source_Index := Source_Index - 1;
-- Record the last character used in reading the numeric literal
Last_Of_Source := Source_Index;
case Current_State is
when S01 | T01 =>
-- In this state we have seen only whitespace
Status := Syntax_Error;
when S07 | S11 | T02 | T05 =>
-- Accept states in which no exponent was given.
-- Simply return the result
Set_Result;
when S09 | T08 =>
-- Return a bad status if an integer has a negative exponent.
if Integral and Numeric_Literals."=" (Sign, Minus) then
Status := Syntax_Error;
else
Set_Result;
end if;
when others =>
-- Nonaccept states
Status := Syntax_Error;
end case;
end Parse_Numeric_Literal;
-------------------------------------------------------
procedure Parse_Enumeration (Source : in String;
Unprintable_Terminators : in Boolean;
Result : out String;
Last : out Natural;
Status : out Parse_Status;
Last_Of_Source : out Natural) is
Source_First_Nonblank : Natural;
Source_Index : Natural := Source'First;
Source_Last : constant Natural := Source'Last;
Id_Length : Natural;
Result_First : constant Natural := Result'First;
Result_Length : constant Natural := Result'Length;
begin
-- First, skip whitespace
-- Whitespace = blanks, tabs, line and page terminators
Last_Of_Source := Source_Last; -- anticipate all blanks or tabs
for I in Source'Range loop
if Class_Map (Source (I)) /= Separator then
if Class_Map (Source (I)) = Terminator then
Last_Of_Source := I - 1;
exit;
else
-- Found non-whitespace
Source_Index := I;
goto E1;
end if;
end if;
end loop;
-- If here, we searched the entire string and found nothing but
-- whitespace
Last := 0;
Status := Empty_Field;
return;
<<E1>> null;
-- Now there are two possibilities. First, we could be looking
-- at an identifier. Second, we could be looking at a character
-- constant.
if Source (Source_Index) /= ''' then
-- We're scanning for an identifier
Source_First_Nonblank := Source_Index;
-- First character must be a letter
if Class_Map (Source (Source_Index)) not in Alphabetic then
goto E2;
end if;
-- We must have letters or digits next, possibly with
-- interspersed single underscores.
loop
Source_Index := Source_Index + 1;
exit when Source_Index > Source_Last;
declare
C : constant Character_Class :=
Class_Map (Source (Source_Index));
begin
if C = Underscore then
-- Eat the '_', and there must be something
-- following, and it must not be '_'
Source_Index := Source_Index + 1;
if Source_Index > Source_Last then
goto E2;
end if;
if Class_Map (Source (Source_Index)) not in
Alphanumeric then
goto E2;
end if;
elsif C not in Alphanumeric then
exit;
end if;
end;
end loop;
-- Here, we have eaten a full identifier, and Source_Index
-- is either past the end of the source, or pointing at the
-- first character past the identifier.
Id_Length := Source_Index - Source_First_Nonblank;
if Result_Length >= Id_Length then
-- The Result will hold the identifier
-- Result (Result_First .. Result_First - 1 + Id_Length) :=
-- Source (Source_First_Nonblank .. Source_Index - 1);
declare
Src_Indx_Kludge : Natural := Source_First_Nonblank;
begin
for I in Result_First .. Result_First - 1 + Id_Length loop
Result (I) := Source (Src_Indx_Kludge);
Src_Indx_Kludge := Src_Indx_Kludge + 1;
end loop;
end;
Last := Result_First + Id_Length - 1;
Status := Ok;
else
-- The Result won't hold the identifier
Last := 0;
Status := Syntax_Error;
end if;
Last_Of_Source := Source_Index - 1;
goto E3;
<<E2>> null;
-- Here there has been some screw-up. Source_Index is pointing
-- at some bad character, or past the end of the string.
Last := 0;
Last_Of_Source := Source_Index - 1;
Status := Syntax_Error;
<<E3>> null;
else
-- Here we have a character constant
-- We know Source (Source_Index) = '''
if Source_Index + 1 > Source_Last or else
Source (Source_Index + 1) not in ' ' .. '~' then
Last := 0;
Last_Of_Source := Source_Index;
Status := Syntax_Error;
elsif Source_Index + 2 > Source_Last or else
Source (Source_Index + 2) /= ''' then
Last := 0;
Last_Of_Source := Source_Index + 1;
Status := Syntax_Error;
else
-- Here we have parsed a character constant
if Result_Length >= 3 then
-- The Result will hold the character constant
Result (Result_First .. Result_First + 2) :=
Source (Source_Index .. Source_Index + 2);
Last := Result_First + 2;
Status := Ok;
else
-- The Result won't hold the character constant
Last := 0;
Status := Syntax_Error;
end if;
Last_Of_Source := Source_Index + 2;
end if;
end if;
end Parse_Enumeration;
end Literal_Parser;