|
|
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: 367029 (0x599b5)
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⟧
-- TITLE aflex - main program
--
-- AUTHOR: John Self (UCI)
-- DESCRIPTION main subprogram of aflex, calls the major routines in order
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/aflex.a,v 1.11 90/10/15 20:00:40 self Exp Locker: self $
--***************************************************************************
-- aflex
-- version 1.1c
--***************************************************************************
--
-- Arcadia Project
-- Department of Information and Computer Science
-- University of California
-- Irvine, California 92717
--
-- Send requests for aflex information to alex-info@ics.uci.edu
--
-- Send bug reports for aflex to alex-bugs@ics.uci.edu
--
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
--
-- This program is based on the flex program written by Vern Paxson.
--
-- The following is the copyright notice from flex, from which aflex is
-- derived.
-- Copyright (c) 1989 The Regents of the University of California.
-- All rights reserved.
--
-- This code is derived from software contributed to Berkeley by
-- Vern Paxson.
--
-- The United States Government has rights in this work pursuant to
-- contract no. DE-AC03-76SF00098 between the United States Department of
-- Energy and the University of California.
--
-- 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, Berkeley. 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
--
--***************************************************************************
with MAIN_BODY, DFA, GEN, MISC_DEFS, TEXT_IO, MISC;
with TSTRING, TEMPLATE_MANAGER, EXTERNAL_FILE_MANAGER; use MISC_DEFS, TEXT_IO,
TSTRING, EXTERNAL_FILE_MANAGER;
function AFLEX return INTEGER is
copyright : constant string :=
"@(#) Copyright (c) 1990 Regents of the University of California.";
copyright2 : constant string :=
"All rights reserved.";
begin
MAIN_BODY.AFLEXINIT;
MAIN_BODY.READIN;
if (SYNTAXERROR) then
MAIN_BODY.AFLEXEND(1);
end if;
if (PERFORMANCE_REPORT) then
if (INTERACTIVE) then
TEXT_IO.PUT_LINE(STANDARD_ERROR,
"-I (interactive) entails a minor performance penalty");
end if;
end if;
if (VARIABLE_TRAILING_CONTEXT_RULES) then
MISC.AFLEXERROR("can't handle variable trailing context rules");
end if;
-- convert the ndfa to a dfa
DFA.NTOD;
-- generate the Ada state transition tables from the DFA
GEN.MAKE_TABLES;
TEMPLATE_MANAGER.GENERATE_IO_FILE;
TEMPLATE_MANAGER.GENERATE_DFA_FILE;
MAIN_BODY.AFLEXEND(0);
return 0;
exception
when MAIN_BODY.AFLEX_TERMINATE =>
return MAIN_BODY.TERMINATION_STATUS;
end AFLEX;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE scanner parser interface
-- AUTHOR: John Self (UCI)
-- DESCRIPTION causes parser to call augmented version of YYLex.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/aflex_scanner.a,v 1.3 90/01/12 15:19:33 self Exp Locker: self $
with PARSE_TOKENS, SCANNER; use PARSE_TOKENS, SCANNER;
package AFLEX_SCANNER is
function YYLEX return TOKEN;
end AFLEX_SCANNER;
with PARSE_TOKENS, SCANNER; use PARSE_TOKENS, SCANNER;
package body AFLEX_SCANNER is
function YYLEX return TOKEN is
begin
return SCANNER.GET_TOKEN;
end YYLEX;
end AFLEX_SCANNER;
-- A lexical scanner generated by aflex
with text_io; use text_io;
with ascan_dfa; use ascan_dfa;
with ascan_io; use ascan_io;
--# line 1 "ascan.l"
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE scanner specification file
-- AUTHOR: John Self (UCI)
-- DESCRIPTION regular expressions and actions matching tokens
-- that aflex expects to find in its input.
-- NOTES input to aflex (NOT alex.) It uses exclusive start conditions
-- and case insensitive scanner generation available only in aflex
-- (or flex if you use C.)
-- generate scanner using the command 'aflex -is ascan.l'
-- $Header: /dc/uc/self/arcadia/aflex/ada/src/RCS/ascan.l,v 1.19 1991/12/03 23:08:24 self Exp self $
--# line 44 "ascan.l"
with misc_defs, misc, sym, parse_tokens, int_io;
with tstring, ascan_dfa, ascan_io, external_file_manager;
use misc_defs, parse_tokens, tstring;
use ascan_dfa, ascan_io, external_file_manager;
package scanner is
call_yylex : boolean := false;
function get_token return Token;
end scanner;
package body scanner is
beglin : boolean := false;
i, bracelevel: integer;
function get_token return Token is
toktype : Token;
didadef, indented_code : boolean;
cclval : integer;
nmdefptr : vstring;
nmdef, tmpbuf : vstring;
procedure ACTION_ECHO is
begin
text_io.put( temp_action_file, yytext(1..YYLength) );
end ACTION_ECHO;
procedure MARK_END_OF_PROLOG is
begin
text_io.put( temp_action_file, "%%%% end of prolog" );
text_io.new_line( temp_action_file );
end MARK_END_OF_PROLOG;
procedure PUT_BACK_STRING(str : vstring; start : integer) is
begin
for i in reverse start+1..tstring.len(str) loop
unput( CHAR(str,i) );
end loop;
end PUT_BACK_STRING;
function check_yylex_here return boolean is
begin
return ( (yytext'length >= 2) and then
((yytext(1) = '#') and (yytext(2) = '#')));
end check_yylex_here;
function YYLex return Token is
subtype short is integer range -32768..32767;
yy_act : integer;
yy_c : short;
-- returned upon end-of-file
YY_END_TOK : constant integer := 0;
YY_END_OF_BUFFER : constant := 82;
subtype yy_state_type is integer;
yy_current_state : yy_state_type;
INITIAL : constant := 0;
SECT2 : constant := 1;
SECT2PROLOG : constant := 2;
SECT3 : constant := 3;
PICKUPDEF : constant := 4;
SC : constant := 5;
CARETISBOL : constant := 6;
NUM : constant := 7;
QUOTE : constant := 8;
FIRSTCCL : constant := 9;
CCL : constant := 10;
ACTION : constant := 11;
RECOVER : constant := 12;
BRACEERROR : constant := 13;
ACTION_STRING : constant := 14;
yy_accept : constant array(0..206) of short :=
( 0,
0, 0, 0, 0, 0, 0, 80, 80, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82, 13, 6, 12, 10, 1, 11, 13, 13, 13,
9, 39, 31, 32, 25, 39, 38, 23, 39, 39,
39, 31, 21, 39, 39, 24, 81, 19, 80, 80,
15, 14, 16, 45, 81, 41, 42, 44, 46, 60,
61, 58, 57, 59, 47, 49, 48, 47, 53, 52,
53, 53, 55, 55, 55, 56, 66, 71, 70, 72,
66, 72, 67, 64, 65, 81, 17, 63, 62, 73,
75, 76, 77, 6, 12, 10, 1, 11, 0, 0,
2, 0, 7, 4, 5, 0, 9, 31, 32, 0,
28, 0, 0, 0, 78, 78, 27, 26, 27, 0,
31, 21, 0, 0, 35, 0, 0, 19, 18, 80,
80, 15, 14, 43, 44, 57, 79, 79, 50, 51,
54, 66, 0, 69, 0, 66, 67, 0, 17, 73,
74, 0, 7, 0, 0, 3, 0, 29, 0, 36,
0, 78, 27, 27, 37, 0, 0, 0, 35, 0,
30, 79, 66, 68, 0, 0, 8, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 22, 0, 22,
0, 22, 4, 0, 34, 0
) ;
yy_ec : constant array(CHARACTER'FIRST..CHARACTER'LAST) of short :=
( 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 4, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 5, 1, 6, 7, 8, 9, 1, 10, 11,
11, 11, 11, 12, 13, 11, 14, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 1, 1, 16,
1, 17, 11, 1, 23, 22, 22, 22, 24, 25,
22, 22, 22, 22, 22, 22, 22, 22, 26, 22,
22, 27, 28, 29, 22, 22, 22, 30, 22, 22,
18, 19, 20, 21, 22, 1, 23, 22, 22, 22,
24, 25, 22, 22, 22, 22, 22, 22, 22, 22,
26, 22, 22, 27, 28, 29, 22, 22, 22, 30,
22, 22, 31, 32, 33, 1, 1
) ;
yy_meta : constant array(0..33) of short :=
( 0,
1, 2, 3, 2, 2, 4, 1, 1, 1, 5,
1, 1, 6, 5, 7, 1, 1, 1, 8, 9,
1, 10, 10, 10, 10, 10, 10, 10, 10, 10,
5, 11, 12
) ;
yy_base : constant array(0..254) of short :=
( 0,
0, 29, 58, 89, 503, 499, 498, 305, 4, 8,
119, 147, 286, 285, 32, 34, 65, 67, 93, 96,
110, 113, 177, 0, 302, 301, 12, 15, 82, 121,
303, 880, 76, 880, 0, 37, 880, 299, 11, 288,
0, 880, 11, 880, 880, 14, 880, 284, 280, 283,
196, 225, 880, 288, 283, 880, 292, 0, 291, 880,
0, 133, 880, 880, 880, 880, 272, 0, 880, 880,
880, 880, 277, 880, 880, 880, 880, 276, 880, 880,
274, 275, 880, 0, 272, 880, 0, 880, 880, 109,
273, 880, 0, 880, 880, 282, 880, 880, 880, 0,
880, 880, 0, 149, 880, 0, 152, 880, 271, 280,
880, 272, 0, 247, 880, 263, 0, 72, 880, 262,
880, 240, 63, 119, 880, 248, 0, 880, 245, 249,
277, 880, 248, 153, 0, 256, 253, 0, 880, 252,
880, 0, 156, 880, 0, 239, 880, 238, 880, 880,
880, 0, 221, 880, 0, 309, 0, 249, 880, 0,
880, 248, 0, 227, 246, 880, 245, 880, 221, 880,
148, 231, 0, 0, 880, 232, 229, 230, 0, 241,
880, 226, 0, 880, 236, 234, 880, 209, 210, 197,
231, 212, 159, 128, 108, 194, 115, 880, 108, 880,
84, 880, 880, 4, 880, 880, 342, 354, 366, 378,
390, 402, 414, 426, 438, 450, 462, 474, 486, 493,
502, 508, 520, 527, 536, 547, 559, 571, 583, 595,
607, 619, 631, 638, 648, 660, 672, 684, 695, 702,
712, 724, 736, 748, 760, 772, 784, 795, 807, 819,
831, 843, 855, 867
) ;
yy_def : constant array(0..254) of short :=
( 0,
207, 207, 208, 208, 209, 209, 210, 210, 211, 211,
212, 212, 213, 213, 214, 214, 215, 215, 216, 216,
217, 217, 206, 23, 218, 218, 213, 213, 219, 219,
206, 206, 206, 206, 220, 221, 206, 222, 223, 206,
224, 206, 225, 206, 206, 206, 206, 206, 226, 227,
228, 229, 206, 206, 206, 206, 230, 231, 232, 206,
233, 206, 206, 206, 206, 206, 206, 234, 206, 206,
206, 206, 206, 206, 206, 206, 206, 227, 206, 206,
235, 236, 206, 237, 227, 206, 238, 206, 206, 239,
238, 206, 240, 206, 206, 241, 206, 206, 206, 242,
206, 206, 243, 206, 206, 220, 221, 206, 206, 222,
206, 206, 244, 206, 206, 245, 224, 225, 206, 246,
206, 206, 226, 226, 206, 206, 247, 206, 247, 206,
229, 206, 206, 246, 248, 249, 230, 231, 206, 232,
206, 233, 206, 206, 234, 206, 206, 206, 206, 206,
206, 238, 239, 206, 239, 206, 240, 241, 206, 242,
206, 250, 244, 206, 245, 206, 246, 206, 206, 206,
226, 206, 247, 129, 206, 206, 249, 246, 248, 249,
206, 206, 156, 206, 251, 250, 206, 206, 206, 226,
252, 253, 254, 206, 206, 226, 252, 206, 253, 206,
254, 206, 206, 206, 206, 0, 206, 206, 206, 206,
206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
206, 206, 206, 206
) ;
yy_nxt : constant array(0..913) of short :=
( 0,
206, 33, 34, 33, 33, 62, 63, 62, 62, 62,
63, 62, 62, 119, 98, 121, 121, 98, 121, 113,
205, 35, 35, 35, 35, 35, 35, 35, 35, 35,
36, 37, 36, 36, 71, 38, 71, 39, 114, 108,
115, 40, 120, 72, 99, 72, 73, 99, 73, 109,
41, 41, 41, 41, 41, 41, 41, 41, 41, 43,
44, 43, 43, 45, 74, 46, 74, 76, 47, 76,
77, 47, 77, 48, 119, 49, 50, 104, 105, 104,
104, 124, 170, 78, 101, 78, 202, 102, 51, 47,
52, 53, 52, 52, 45, 65, 46, 54, 65, 47,
103, 55, 47, 120, 48, 80, 49, 50, 80, 56,
200, 81, 65, 82, 81, 65, 82, 198, 154, 51,
47, 65, 84, 101, 204, 84, 102, 155, 85, 86,
66, 85, 86, 171, 143, 67, 143, 143, 123, 103,
68, 68, 68, 68, 68, 68, 68, 68, 68, 65,
104, 105, 104, 104, 108, 168, 203, 143, 66, 143,
143, 202, 190, 67, 109, 178, 124, 170, 68, 68,
68, 68, 68, 68, 68, 68, 68, 87, 87, 88,
87, 87, 89, 87, 87, 87, 90, 87, 87, 91,
92, 87, 87, 87, 87, 87, 87, 87, 93, 93,
93, 93, 93, 93, 93, 93, 93, 94, 87, 95,
128, 196, 124, 170, 200, 124, 170, 129, 129, 129,
129, 129, 129, 129, 129, 129, 131, 132, 131, 131,
154, 181, 168, 198, 195, 194, 187, 133, 184, 155,
147, 192, 193, 181, 191, 125, 189, 168, 166, 188,
187, 159, 182, 146, 141, 138, 134, 174, 181, 174,
177, 176, 172, 169, 168, 166, 174, 174, 174, 174,
174, 174, 174, 174, 174, 164, 162, 175, 131, 132,
131, 131, 111, 116, 159, 156, 126, 150, 148, 133,
126, 146, 144, 141, 138, 136, 135, 126, 124, 122,
116, 111, 206, 97, 97, 69, 69, 60, 134, 183,
183, 184, 183, 183, 185, 183, 183, 183, 185, 183,
183, 183, 185, 183, 183, 183, 183, 183, 183, 183,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
183, 185, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 42, 42, 42, 42, 42, 42,
42, 42, 42, 42, 42, 42, 57, 57, 57, 57,
57, 57, 57, 57, 57, 57, 57, 57, 59, 59,
59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
61, 61, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 70, 70, 70, 70,
70, 70, 70, 70, 70, 70, 70, 70, 75, 75,
75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
79, 79, 83, 83, 83, 83, 83, 83, 83, 83,
83, 83, 83, 83, 96, 96, 96, 96, 96, 96,
96, 96, 96, 96, 96, 96, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 106, 106,
60, 58, 106, 107, 107, 58, 206, 107, 110, 110,
110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
112, 112, 112, 112, 112, 112, 112, 112, 112, 112,
112, 112, 117, 117, 206, 206, 117, 118, 118, 206,
206, 206, 206, 206, 206, 206, 118, 123, 123, 206,
123, 123, 123, 123, 123, 206, 123, 123, 123, 125,
125, 206, 125, 125, 125, 125, 125, 125, 125, 125,
125, 127, 127, 206, 127, 127, 127, 127, 127, 127,
127, 127, 127, 130, 130, 130, 130, 130, 130, 130,
130, 130, 130, 130, 130, 137, 137, 137, 137, 137,
137, 137, 137, 137, 137, 137, 137, 139, 206, 206,
139, 139, 139, 139, 139, 139, 139, 139, 139, 140,
140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
140, 142, 142, 206, 142, 142, 142, 142, 142, 142,
142, 142, 142, 145, 145, 206, 206, 145, 147, 147,
206, 147, 147, 147, 147, 147, 147, 147, 147, 147,
149, 149, 206, 149, 149, 149, 149, 149, 149, 149,
149, 149, 151, 151, 206, 151, 151, 151, 151, 151,
206, 151, 151, 151, 152, 152, 206, 206, 206, 152,
152, 152, 152, 206, 152, 153, 153, 206, 153, 153,
153, 153, 153, 153, 153, 153, 153, 157, 157, 206,
206, 157, 158, 158, 158, 158, 158, 158, 158, 158,
158, 158, 158, 158, 160, 160, 206, 206, 160, 160,
160, 206, 160, 160, 160, 160, 161, 161, 206, 161,
161, 161, 161, 161, 161, 161, 161, 161, 163, 163,
206, 163, 163, 163, 163, 163, 163, 163, 163, 163,
165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
165, 165, 167, 167, 167, 167, 167, 167, 167, 167,
167, 167, 167, 167, 173, 173, 206, 173, 173, 173,
173, 173, 173, 173, 173, 179, 179, 206, 179, 179,
179, 179, 179, 179, 179, 179, 179, 180, 180, 180,
180, 180, 180, 180, 180, 180, 180, 180, 180, 186,
186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
186, 185, 185, 185, 185, 185, 185, 185, 185, 185,
185, 185, 185, 197, 197, 197, 197, 197, 197, 197,
197, 197, 197, 197, 197, 199, 199, 199, 199, 199,
199, 199, 199, 199, 199, 199, 199, 201, 201, 201,
201, 201, 201, 201, 201, 201, 201, 201, 201, 31,
206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
206, 206, 206
) ;
yy_chk : constant array(0..913) of short :=
( 0,
0, 1, 1, 1, 1, 9, 9, 9, 9, 10,
10, 10, 10, 43, 27, 46, 46, 28, 46, 39,
204, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 15, 2, 16, 2, 39, 36,
39, 2, 43, 15, 27, 16, 15, 28, 16, 36,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
3, 3, 3, 3, 15, 3, 16, 17, 3, 18,
17, 3, 18, 3, 118, 3, 3, 33, 33, 33,
33, 123, 123, 17, 29, 18, 201, 29, 3, 3,
4, 4, 4, 4, 4, 19, 4, 4, 20, 4,
29, 4, 4, 118, 4, 19, 4, 4, 20, 4,
199, 19, 21, 19, 20, 22, 20, 197, 90, 4,
4, 11, 21, 30, 195, 22, 30, 90, 21, 21,
11, 22, 22, 124, 62, 11, 62, 62, 124, 30,
11, 11, 11, 11, 11, 11, 11, 11, 11, 12,
104, 104, 104, 104, 107, 134, 194, 143, 12, 143,
143, 193, 171, 12, 107, 134, 171, 171, 12, 12,
12, 12, 12, 12, 12, 12, 12, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
51, 190, 196, 196, 192, 190, 190, 51, 51, 51,
51, 51, 51, 51, 51, 51, 52, 52, 52, 52,
153, 177, 178, 191, 189, 188, 186, 52, 185, 153,
182, 177, 178, 180, 176, 172, 169, 167, 165, 164,
162, 158, 148, 146, 140, 137, 52, 129, 136, 129,
133, 130, 126, 122, 120, 116, 129, 129, 129, 129,
129, 129, 129, 129, 129, 114, 112, 129, 131, 131,
131, 131, 110, 109, 96, 91, 85, 82, 81, 131,
78, 73, 67, 59, 57, 55, 54, 50, 49, 48,
40, 38, 31, 26, 25, 14, 13, 8, 131, 156,
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
156, 156, 207, 207, 207, 207, 207, 207, 207, 207,
207, 207, 207, 207, 208, 208, 208, 208, 208, 208,
208, 208, 208, 208, 208, 208, 209, 209, 209, 209,
209, 209, 209, 209, 209, 209, 209, 209, 210, 210,
210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
211, 211, 212, 212, 212, 212, 212, 212, 212, 212,
212, 212, 212, 212, 213, 213, 213, 213, 213, 213,
213, 213, 213, 213, 213, 213, 214, 214, 214, 214,
214, 214, 214, 214, 214, 214, 214, 214, 215, 215,
215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
216, 216, 217, 217, 217, 217, 217, 217, 217, 217,
217, 217, 217, 217, 218, 218, 218, 218, 218, 218,
218, 218, 218, 218, 218, 218, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 220, 220,
7, 6, 220, 221, 221, 5, 0, 221, 222, 222,
222, 222, 222, 222, 222, 222, 222, 222, 222, 222,
223, 223, 223, 223, 223, 223, 223, 223, 223, 223,
223, 223, 224, 224, 0, 0, 224, 225, 225, 0,
0, 0, 0, 0, 0, 0, 225, 226, 226, 0,
226, 226, 226, 226, 226, 0, 226, 226, 226, 227,
227, 0, 227, 227, 227, 227, 227, 227, 227, 227,
227, 228, 228, 0, 228, 228, 228, 228, 228, 228,
228, 228, 228, 229, 229, 229, 229, 229, 229, 229,
229, 229, 229, 229, 229, 230, 230, 230, 230, 230,
230, 230, 230, 230, 230, 230, 230, 231, 0, 0,
231, 231, 231, 231, 231, 231, 231, 231, 231, 232,
232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
232, 233, 233, 0, 233, 233, 233, 233, 233, 233,
233, 233, 233, 234, 234, 0, 0, 234, 235, 235,
0, 235, 235, 235, 235, 235, 235, 235, 235, 235,
236, 236, 0, 236, 236, 236, 236, 236, 236, 236,
236, 236, 237, 237, 0, 237, 237, 237, 237, 237,
0, 237, 237, 237, 238, 238, 0, 0, 0, 238,
238, 238, 238, 0, 238, 239, 239, 0, 239, 239,
239, 239, 239, 239, 239, 239, 239, 240, 240, 0,
0, 240, 241, 241, 241, 241, 241, 241, 241, 241,
241, 241, 241, 241, 242, 242, 0, 0, 242, 242,
242, 0, 242, 242, 242, 242, 243, 243, 0, 243,
243, 243, 243, 243, 243, 243, 243, 243, 244, 244,
0, 244, 244, 244, 244, 244, 244, 244, 244, 244,
245, 245, 245, 245, 245, 245, 245, 245, 245, 245,
245, 245, 246, 246, 246, 246, 246, 246, 246, 246,
246, 246, 246, 246, 247, 247, 0, 247, 247, 247,
247, 247, 247, 247, 247, 248, 248, 0, 248, 248,
248, 248, 248, 248, 248, 248, 248, 249, 249, 249,
249, 249, 249, 249, 249, 249, 249, 249, 249, 250,
250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
250, 251, 251, 251, 251, 251, 251, 251, 251, 251,
251, 251, 251, 252, 252, 252, 252, 252, 252, 252,
252, 252, 252, 252, 252, 253, 253, 253, 253, 253,
253, 253, 253, 253, 253, 253, 253, 254, 254, 254,
254, 254, 254, 254, 254, 254, 254, 254, 254, 206,
206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
206, 206, 206
) ;
-- copy whatever the last rule matched to the standard output
procedure ECHO is
begin
text_io.put( yytext );
end ECHO;
-- enter a start condition.
-- Using procedure requires a () after the ENTER, but makes everything
-- much neater.
procedure ENTER( state : integer ) is
begin
yy_start := 1 + 2 * state;
end ENTER;
-- action number for EOF rule of a given start state
function YY_STATE_EOF(state : integer) return integer is
begin
return YY_END_OF_BUFFER + state + 1;
end YY_STATE_EOF;
-- return all but the first 'n' matched characters back to the input stream
procedure yyless(n : integer) is
begin
yy_ch_buf(yy_cp) := yy_hold_char; -- undo effects of setting up yytext
yy_cp := yy_bp + n;
yy_c_buf_p := yy_cp;
YY_DO_BEFORE_ACTION; -- set up yytext again
end yyless;
-- redefine this if you have something you want each time.
procedure YY_USER_ACTION is
begin
null;
end;
-- yy_get_previous_state - get the state just before the EOB char was reached
function yy_get_previous_state return yy_state_type is
yy_current_state : yy_state_type;
yy_c : short;
yy_bp : integer := yytext_ptr;
begin
yy_current_state := yy_start;
if ( yy_ch_buf(yy_bp-1) = ASCII.LF ) then
yy_current_state := yy_current_state + 1;
end if;
for yy_cp in yytext_ptr..yy_c_buf_p - 1 loop
yy_c := yy_ec(yy_ch_buf(yy_cp));
if ( yy_accept(yy_current_state) /= 0 ) then
yy_last_accepting_state := yy_current_state;
yy_last_accepting_cpos := yy_cp;
end if;
while ( yy_chk(yy_base(yy_current_state) + yy_c) /= yy_current_state ) loop
yy_current_state := yy_def(yy_current_state);
if ( yy_current_state >= 207 ) then
yy_c := yy_meta(yy_c);
end if;
end loop;
yy_current_state := yy_nxt(yy_base(yy_current_state) + yy_c);
end loop;
return yy_current_state;
end yy_get_previous_state;
procedure yyrestart( input_file : file_type ) is
begin
set_input(input_file);
yy_init := true;
end yyrestart;
begin -- of YYLex
<<new_file>>
-- this is where we enter upon encountering an end-of-file and
-- yywrap() indicating that we should continue processing
if ( yy_init ) then
if ( yy_start = 0 ) then
yy_start := 1; -- first start state
end if;
-- we put in the '\n' and start reading from [1] so that an
-- initial match-at-newline will be true.
yy_ch_buf(0) := ASCII.LF;
yy_n_chars := 1;
-- we always need two end-of-buffer characters. The first causes
-- a transition to the end-of-buffer state. The second causes
-- a jam in that state.
yy_ch_buf(yy_n_chars) := YY_END_OF_BUFFER_CHAR;
yy_ch_buf(yy_n_chars + 1) := YY_END_OF_BUFFER_CHAR;
yy_eof_has_been_seen := false;
yytext_ptr := 1;
yy_c_buf_p := yytext_ptr;
yy_hold_char := yy_ch_buf(yy_c_buf_p);
yy_init := false;
end if; -- yy_init
loop -- loops until end-of-file is reached
yy_cp := yy_c_buf_p;
-- support of yytext
yy_ch_buf(yy_cp) := yy_hold_char;
-- yy_bp points to the position in yy_ch_buf of the start of the
-- current run.
yy_bp := yy_cp;
yy_current_state := yy_start;
if ( yy_ch_buf(yy_bp-1) = ASCII.LF ) then
yy_current_state := yy_current_state + 1;
end if;
loop
yy_c := yy_ec(yy_ch_buf(yy_cp));
if ( yy_accept(yy_current_state) /= 0 ) then
yy_last_accepting_state := yy_current_state;
yy_last_accepting_cpos := yy_cp;
end if;
while ( yy_chk(yy_base(yy_current_state) + yy_c) /= yy_current_state ) loop
yy_current_state := yy_def(yy_current_state);
if ( yy_current_state >= 207 ) then
yy_c := yy_meta(yy_c);
end if;
end loop;
yy_current_state := yy_nxt(yy_base(yy_current_state) + yy_c);
yy_cp := yy_cp + 1;
if ( yy_current_state = 206 ) then
exit;
end if;
end loop;
yy_cp := yy_last_accepting_cpos;
yy_current_state := yy_last_accepting_state;
<<next_action>>
yy_act := yy_accept(yy_current_state);
YY_DO_BEFORE_ACTION;
YY_USER_ACTION;
if aflex_debug then -- output acceptance info. for (-d) debug mode
text_io.put( Standard_Error, "--accepting rule #" );
text_io.put( Standard_Error, INTEGER'IMAGE(yy_act) );
text_io.put_line( Standard_Error, "(""" & yytext & """)");
end if;
<<do_action>> -- this label is used only to access EOF actions
case yy_act is
when 0 => -- must backtrack
-- undo the effects of YY_DO_BEFORE_ACTION
yy_ch_buf(yy_cp) := yy_hold_char;
yy_cp := yy_last_accepting_cpos;
yy_current_state := yy_last_accepting_state;
goto next_action;
when 1 =>
--# line 46 "ascan.l"
indented_code := true;
when 2 =>
--# line 47 "ascan.l"
linenum := linenum + 1; ECHO;
-- treat as a comment;
when 3 =>
--# line 50 "ascan.l"
linenum := linenum + 1; ECHO;
when 4 =>
--# line 51 "ascan.l"
return ( SCDECL );
when 5 =>
--# line 52 "ascan.l"
return ( XSCDECL );
when 6 =>
--# line 54 "ascan.l"
return ( WHITESPACE );
when 7 =>
--# line 56 "ascan.l"
sectnum := 2;
misc.line_directive_out;
ENTER(SECT2PROLOG);
return ( SECTEND );
when 8 =>
--# line 63 "ascan.l"
text_io.put( Standard_Error, "old-style lex command at line " );
int_io.put( Standard_Error, linenum );
text_io.put( Standard_Error, "ignored:" );
text_io.new_line( Standard_Error );
text_io.put( Standard_Error, ASCII.HT );
text_io.put( Standard_Error, yytext(1..YYLength) );
linenum := linenum + 1;
when 9 =>
--# line 73 "ascan.l"
nmstr := vstr(yytext(1..YYLength));
didadef := false;
ENTER(PICKUPDEF);
when 10 =>
--# line 79 "ascan.l"
nmstr := vstr(yytext(1..YYLength));
return NAME;
when 11 =>
--# line 82 "ascan.l"
linenum := linenum + 1;
-- allows blank lines in section 1;
when 12 =>
--# line 85 "ascan.l"
linenum := linenum + 1; return Newline;
when 13 =>
--# line 86 "ascan.l"
misc.synerr( "illegal character" );ENTER(RECOVER);
when 14 =>
--# line 88 "ascan.l"
null;
-- separates name and definition;
when 15 =>
--# line 92 "ascan.l"
nmdef := vstr(yytext(1..YYLength));
i := tstring.len( nmdef );
while ( i >= tstring.first ) loop
if ( (CHAR(nmdef,i) /= ' ') and
(CHAR(nmdef,i) /= ASCII.HT) ) then
exit;
end if;
i := i - 1;
end loop;
sym.ndinstal( nmstr,
tstring.slice(nmdef, tstring.first, i) );
didadef := true;
when 16 =>
--# line 109 "ascan.l"
if ( not didadef ) then
misc.synerr( "incomplete name definition" );
end if;
ENTER(0);
linenum := linenum + 1;
when 17 =>
--# line 117 "ascan.l"
linenum := linenum + 1;
ENTER(0);
nmstr := vstr(yytext(1..YYLength));
return NAME;
when 18 =>
yy_ch_buf(yy_cp) := yy_hold_char; -- undo effects of setting up yytext
yy_cp := yy_cp - 1;
yy_c_buf_p := yy_cp;
YY_DO_BEFORE_ACTION; -- set up yytext again
--# line 123 "ascan.l"
linenum := linenum + 1;
ACTION_ECHO;
MARK_END_OF_PROLOG;
ENTER(SECT2);
when 19 =>
--# line 130 "ascan.l"
linenum := linenum + 1; ACTION_ECHO;
when YY_END_OF_BUFFER +SECT2PROLOG + 1
=>
--# line 132 "ascan.l"
MARK_END_OF_PROLOG;
return End_Of_Input;
when 21 =>
--# line 136 "ascan.l"
linenum := linenum + 1;
-- allow blank lines in sect2;
-- this rule matches indented lines which
-- are not comments.
when 22 =>
--# line 141 "ascan.l"
misc.synerr("indented code found outside of action");
linenum := linenum + 1;
when 23 =>
--# line 146 "ascan.l"
ENTER(SC); return ( '<' );
when 24 =>
--# line 147 "ascan.l"
return ( '^' );
when 25 =>
--# line 148 "ascan.l"
ENTER(QUOTE); return ( '"' );
when 26 =>
yy_ch_buf(yy_cp) := yy_hold_char; -- undo effects of setting up yytext
yy_cp := yy_bp + 1;
yy_c_buf_p := yy_cp;
YY_DO_BEFORE_ACTION; -- set up yytext again
--# line 149 "ascan.l"
ENTER(NUM); return ( '{' );
when 27 =>
--# line 150 "ascan.l"
ENTER(BRACEERROR);
when 28 =>
yy_ch_buf(yy_cp) := yy_hold_char; -- undo effects of setting up yytext
yy_cp := yy_bp + 1;
yy_c_buf_p := yy_cp;
YY_DO_BEFORE_ACTION; -- set up yytext again
--# line 151 "ascan.l"
return ( '$' );
when 29 =>
--# line 153 "ascan.l"
continued_action := true;
linenum := linenum + 1;
return Newline;
when 30 =>
--# line 158 "ascan.l"
linenum := linenum + 1; ACTION_ECHO;
when 31 =>
--# line 160 "ascan.l"
-- this rule is separate from the one below because
-- otherwise we get variable trailing context, so
-- we can't build the scanner using -f,F
bracelevel := 0;
continued_action := false;
ENTER(ACTION);
return Newline;
when 32 =>
yy_ch_buf(yy_cp) := yy_hold_char; -- undo effects of setting up yytext
yy_cp := yy_cp - 1;
yy_c_buf_p := yy_cp;
YY_DO_BEFORE_ACTION; -- set up yytext again
--# line 171 "ascan.l"
bracelevel := 0;
continued_action := false;
ENTER(ACTION);
return Newline;
when 33 =>
--# line 178 "ascan.l"
linenum := linenum + 1; return Newline;
when 34 =>
--# line 180 "ascan.l"
return ( EOF_OP );
when 35 =>
--# line 182 "ascan.l"
sectnum := 3;
ENTER(SECT3);
return ( End_Of_Input );
-- to stop the parser
when 36 =>
--# line 189 "ascan.l"
nmstr := vstr(yytext(1..YYLength));
-- check to see if we've already encountered this ccl
cclval := sym.ccllookup( nmstr );
if ( cclval /= 0 ) then
yylval := cclval;
cclreuse := cclreuse + 1;
return ( PREVCCL );
else
-- we fudge a bit. We know that this ccl will
-- soon be numbered as lastccl + 1 by cclinit
sym.cclinstal( nmstr, lastccl + 1 );
-- push back everything but the leading bracket
-- so the ccl can be rescanned
PUT_BACK_STRING(nmstr, 1);
ENTER(FIRSTCCL);
return ( '[' );
end if;
when 37 =>
--# line 214 "ascan.l"
nmstr := vstr(yytext(1..YYLength));
-- chop leading and trailing brace
tmpbuf := slice(vstr(yytext(1..YYLength)),
2, YYLength-1);
nmdefptr := sym.ndlookup( tmpbuf );
if ( nmdefptr = NUL ) then
misc.synerr( "undefined {name}" );
else
-- push back name surrounded by ()'s
unput(')');
PUT_BACK_STRING(nmdefptr, 0);
unput('(');
end if;
when 38 =>
--# line 231 "ascan.l"
tmpbuf := vstr(yytext(1..YYLength));
case tstring.CHAR(tmpbuf,1) is
when '/' => return '/';
when '|' => return '|';
when '*' => return '*';
when '+' => return '+';
when '?' => return '?';
when '.' => return '.';
when '(' => return '(';
when ')' => return ')';
when others =>
misc.aflexerror("error in aflex case");
end case;
when 39 =>
--# line 245 "ascan.l"
tmpbuf := vstr(yytext(1..YYLength));
yylval := CHARACTER'POS(CHAR(tmpbuf,1));
return CHAR;
when 40 =>
--# line 249 "ascan.l"
linenum := linenum + 1; return Newline;
when 41 =>
--# line 252 "ascan.l"
return ( ',' );
when 42 =>
--# line 253 "ascan.l"
ENTER(SECT2); return ( '>' );
when 43 =>
yy_ch_buf(yy_cp) := yy_hold_char; -- undo effects of setting up yytext
yy_cp := yy_bp + 1;
yy_c_buf_p := yy_cp;
YY_DO_BEFORE_ACTION; -- set up yytext again
--# line 254 "ascan.l"
ENTER(CARETISBOL); return ( '>' );
when 44 =>
--# line 255 "ascan.l"
nmstr := vstr(yytext(1..YYLength));
return NAME;
when 45 =>
--# line 258 "ascan.l"
misc.synerr( "bad start condition name" );
when 46 =>
--# line 260 "ascan.l"
ENTER(SECT2); return ( '^' );
when 47 =>
--# line 263 "ascan.l"
tmpbuf := vstr(yytext(1..YYLength));
yylval := CHARACTER'POS(CHAR(tmpbuf,1));
return CHAR;
when 48 =>
--# line 267 "ascan.l"
ENTER(SECT2); return ( '"' );
when 49 =>
--# line 269 "ascan.l"
misc.synerr( "missing quote" );
ENTER(SECT2);
linenum := linenum + 1;
return ( '"' );
when 50 =>
yy_ch_buf(yy_cp) := yy_hold_char; -- undo effects of setting up yytext
yy_cp := yy_bp + 1;
yy_c_buf_p := yy_cp;
YY_DO_BEFORE_ACTION; -- set up yytext again
--# line 277 "ascan.l"
ENTER(CCL); return ( '^' );
when 51 =>
yy_ch_buf(yy_cp) := yy_hold_char; -- undo effects of setting up yytext
yy_cp := yy_bp + 1;
yy_c_buf_p := yy_cp;
YY_DO_BEFORE_ACTION; -- set up yytext again
--# line 278 "ascan.l"
return ( '^' );
when 52 =>
--# line 279 "ascan.l"
ENTER(CCL); yylval := CHARACTER'POS('-'); return ( CHAR );
when 53 =>
--# line 280 "ascan.l"
ENTER(CCL);
tmpbuf := vstr(yytext(1..YYLength));
yylval := CHARACTER'POS(CHAR(tmpbuf,1));
return CHAR;
when 54 =>
yy_ch_buf(yy_cp) := yy_hold_char; -- undo effects of setting up yytext
yy_cp := yy_bp + 1;
yy_c_buf_p := yy_cp;
YY_DO_BEFORE_ACTION; -- set up yytext again
--# line 286 "ascan.l"
return ( '-' );
when 55 =>
--# line 287 "ascan.l"
tmpbuf := vstr(yytext(1..YYLength));
yylval := CHARACTER'POS(CHAR(tmpbuf,1));
return CHAR;
when 56 =>
--# line 291 "ascan.l"
ENTER(SECT2); return ( ']' );
when 57 =>
--# line 294 "ascan.l"
yylval := misc.myctoi( vstr(yytext(1..YYLength)) );
return ( NUMBER );
when 58 =>
--# line 299 "ascan.l"
return ( ',' );
when 59 =>
--# line 300 "ascan.l"
ENTER(SECT2); return ( '}' );
when 60 =>
--# line 302 "ascan.l"
misc.synerr( "bad character inside {}'s" );
ENTER(SECT2);
return ( '}' );
when 61 =>
--# line 308 "ascan.l"
misc.synerr( "missing }" );
ENTER(SECT2);
linenum := linenum + 1;
return ( '}' );
when 62 =>
--# line 316 "ascan.l"
misc.synerr( "bad name in {}'s" ); ENTER(SECT2);
when 63 =>
--# line 317 "ascan.l"
misc.synerr( "missing }" );
linenum := linenum + 1;
ENTER(SECT2);
when 64 =>
--# line 322 "ascan.l"
bracelevel := bracelevel + 1;
when 65 =>
--# line 323 "ascan.l"
bracelevel := bracelevel - 1;
when 66 =>
--# line 324 "ascan.l"
ACTION_ECHO;
when 67 =>
--# line 325 "ascan.l"
ACTION_ECHO;
when 68 =>
--# line 326 "ascan.l"
linenum := linenum + 1; ACTION_ECHO;
when 69 =>
--# line 327 "ascan.l"
ACTION_ECHO;
-- character constant;
when 70 =>
--# line 331 "ascan.l"
ACTION_ECHO; ENTER(ACTION_STRING);
when 71 =>
--# line 333 "ascan.l"
linenum := linenum + 1;
ACTION_ECHO;
if ( bracelevel = 0 ) then
text_io.new_line ( temp_action_file );
ENTER(SECT2);
end if;
when 72 =>
--# line 341 "ascan.l"
ACTION_ECHO;
when 73 =>
--# line 343 "ascan.l"
ACTION_ECHO;
when 74 =>
--# line 344 "ascan.l"
ACTION_ECHO;
when 75 =>
--# line 345 "ascan.l"
linenum := linenum + 1; ACTION_ECHO;
when 76 =>
--# line 346 "ascan.l"
ACTION_ECHO; ENTER(ACTION);
when 77 =>
--# line 347 "ascan.l"
ACTION_ECHO;
when 78 =>
--# line 350 "ascan.l"
yylval := CHARACTER'POS(misc.myesc( vstr(yytext(1..YYLength)) ));
return ( CHAR );
when 79 =>
--# line 355 "ascan.l"
yylval := CHARACTER'POS(misc.myesc( vstr(yytext(1..YYLength)) ));
ENTER(CCL);
return ( CHAR );
when 80 =>
--# line 362 "ascan.l"
if ( check_yylex_here ) then
return End_Of_Input;
else
ECHO;
end if;
when 81 =>
--# line 368 "ascan.l"
raise AFLEX_SCANNER_JAMMED;
when YY_END_OF_BUFFER + INITIAL + 1 |
YY_END_OF_BUFFER + SECT2 + 1 |
YY_END_OF_BUFFER + SECT3 + 1 |
YY_END_OF_BUFFER + PICKUPDEF + 1 |
YY_END_OF_BUFFER + SC + 1 |
YY_END_OF_BUFFER + CARETISBOL + 1 |
YY_END_OF_BUFFER + NUM + 1 |
YY_END_OF_BUFFER + QUOTE + 1 |
YY_END_OF_BUFFER + FIRSTCCL + 1 |
YY_END_OF_BUFFER + CCL + 1 |
YY_END_OF_BUFFER + ACTION + 1 |
YY_END_OF_BUFFER + RECOVER + 1 |
YY_END_OF_BUFFER + BRACEERROR + 1 |
YY_END_OF_BUFFER + ACTION_STRING + 1 =>
return End_Of_Input;
when YY_END_OF_BUFFER =>
-- undo the effects of YY_DO_BEFORE_ACTION
yy_ch_buf(yy_cp) := yy_hold_char;
yytext_ptr := yy_bp;
case yy_get_next_buffer is
when EOB_ACT_END_OF_FILE =>
begin
if ( yywrap ) then
-- note: because we've taken care in
-- yy_get_next_buffer() to have set up yytext,
-- we can now set up yy_c_buf_p so that if some
-- total hoser (like aflex itself) wants
-- to call the scanner after we return the
-- End_Of_Input, it'll still work - another
-- End_Of_Input will get returned.
yy_c_buf_p := yytext_ptr;
yy_act := YY_STATE_EOF((yy_start - 1) / 2);
goto do_action;
else
-- start processing a new file
yy_init := true;
goto new_file;
end if;
end;
when EOB_ACT_RESTART_SCAN =>
yy_c_buf_p := yytext_ptr;
yy_hold_char := yy_ch_buf(yy_c_buf_p);
when EOB_ACT_LAST_MATCH =>
yy_c_buf_p := yy_n_chars;
yy_current_state := yy_get_previous_state;
yy_cp := yy_c_buf_p;
yy_bp := yytext_ptr;
goto next_action;
when others => null;
end case; -- case yy_get_next_buffer()
when others =>
text_io.put( "action # " );
text_io.put( INTEGER'IMAGE(yy_act) );
text_io.new_line;
raise AFLEX_INTERNAL_ERROR;
end case; -- case (yy_act)
end loop; -- end of loop waiting for end of file
end YYLex;
--# line 368 "ascan.l"
begin
if (call_yylex) then
toktype := YYLex;
call_yylex := false;
return toktype;
end if;
if ( eofseen ) then
toktype := End_Of_Input;
else
toktype := YYLex;
end if;
-- this tracing code allows easy tracing of aflex runs
if (trace) then
text_io.new_line(Standard_Error);
text_io.put(Standard_Error, "toktype = :" );
text_io.put(Standard_Error, Token'image(toktype));
text_io.put_line(Standard_Error, ":" );
end if;
if ( toktype = End_Of_Input ) then
eofseen := true;
if ( sectnum = 1 ) then
misc.synerr( "unexpected EOF" );
sectnum := 2;
toktype := SECTEND;
else
if ( sectnum = 2 ) then
sectnum := 3;
toktype := SECTEND;
end if;
end if;
end if;
if ( trace ) then
if ( beglin ) then
int_io.put( Standard_Error, num_rules + 1 );
text_io.put( Standard_Error, ASCII.HT );
beglin := false;
end if;
case toktype is
when '<' | '>'|'^'|'$'|'"'|'['|']'|'{'|'}'|'|'|'('|
')'|'-'|'/'|'?'|'.'|'*'|'+'|',' =>
text_io.put( Standard_Error, Token'image(toktype) );
when NEWLINE =>
text_io.new_line(Standard_Error);
if ( sectnum = 2 ) then
beglin := true;
end if;
when SCDECL =>
text_io.put( Standard_Error, "%s" );
when XSCDECL =>
text_io.put( Standard_Error, "%x" );
when WHITESPACE =>
text_io.put( Standard_Error, " " );
when SECTEND =>
text_io.put_line( Standard_Error, "%%" );
-- we set beglin to be true so we'll start
-- writing out numbers as we echo rules. aflexscan() has
-- already assigned sectnum
if ( sectnum = 2 ) then
beglin := true;
end if;
when NAME =>
text_io.put( Standard_Error, ''' );
text_io.put( Standard_Error, YYText);
text_io.put( Standard_Error, ''' );
when CHAR =>
if ( (yylval < CHARACTER'POS(' ')) or
(yylval = CHARACTER'POS(ASCII.DEL)) ) then
text_io.put( Standard_Error, '\' );
int_io.put( Standard_Error, yylval );
text_io.put( Standard_Error, '\' );
else
text_io.put( Standard_Error, Token'image(toktype) );
end if;
when NUMBER =>
int_io.put( Standard_Error, yylval );
when PREVCCL =>
text_io.put( Standard_Error, '[' );
int_io.put( Standard_Error, yylval );
text_io.put( Standard_Error, ']' );
when End_Of_Input =>
text_io.put( Standard_Error, "End Marker" );
when others =>
text_io.put( Standard_Error, "Something weird:" );
text_io.put_line( Standard_Error, Token'image(toktype));
end case;
end if;
return toktype;
end get_token;
end scanner;
package ascan_dfa is
aflex_debug : boolean := false;
yytext_ptr : integer; -- points to start of yytext in buffer
-- yy_ch_buf has to be 2 characters longer than YY_BUF_SIZE because we need
-- to put in 2 end-of-buffer characters (this is explained where it is
-- done) at the end of yy_ch_buf
YY_READ_BUF_SIZE : constant integer := 8192;
YY_BUF_SIZE : constant integer := YY_READ_BUF_SIZE * 2; -- size of input buffer
type unbounded_character_array is array(integer range <>) of character;
subtype ch_buf_type is unbounded_character_array(0..YY_BUF_SIZE + 1);
yy_ch_buf : ch_buf_type;
yy_cp, yy_bp : integer;
-- yy_hold_char holds the character lost when yytext is formed
yy_hold_char : character;
yy_c_buf_p : integer; -- points to current character in buffer
function YYText return string;
function YYLength return integer;
procedure YY_DO_BEFORE_ACTION;
--These variables are needed between calls to YYLex.
yy_init : boolean := true; -- do we need to initialize YYLex?
yy_start : integer := 0; -- current start state number
subtype yy_state_type is integer;
yy_last_accepting_state : yy_state_type;
yy_last_accepting_cpos : integer;
end ascan_dfa;
with ascan_dfa; use ascan_dfa;
package body ascan_dfa is
function YYText return string is
i : integer;
str_loc : integer := 1;
buffer : string(1..1024);
EMPTY_STRING : constant string := "";
begin
-- find end of buffer
i := yytext_ptr;
while ( yy_ch_buf(i) /= ASCII.NUL ) loop
buffer(str_loc ) := yy_ch_buf(i);
i := i + 1;
str_loc := str_loc + 1;
end loop;
-- return yy_ch_buf(yytext_ptr.. i - 1);
if (str_loc < 2) then
return EMPTY_STRING;
else
return buffer(1..str_loc-1);
end if;
end;
-- returns the length of the matched text
function YYLength return integer is
begin
return yy_cp - yy_bp;
end YYLength;
-- done after the current pattern has been matched and before the
-- corresponding action - sets up yytext
procedure YY_DO_BEFORE_ACTION is
begin
yytext_ptr := yy_bp;
yy_hold_char := yy_ch_buf(yy_cp);
yy_ch_buf(yy_cp) := ASCII.NUL;
yy_c_buf_p := yy_cp;
end YY_DO_BEFORE_ACTION;
end ascan_dfa;
with ascan_dfa; use ascan_dfa;
with text_io; use text_io;
package ascan_io is
NULL_IN_INPUT : exception;
AFLEX_INTERNAL_ERROR : exception;
UNEXPECTED_LAST_MATCH : exception;
PUSHBACK_OVERFLOW : exception;
AFLEX_SCANNER_JAMMED : exception;
type eob_action_type is ( EOB_ACT_RESTART_SCAN,
EOB_ACT_END_OF_FILE,
EOB_ACT_LAST_MATCH );
YY_END_OF_BUFFER_CHAR : constant character:= ASCII.NUL;
yy_n_chars : integer; -- number of characters read into yy_ch_buf
-- true when we've seen an EOF for the current input file
yy_eof_has_been_seen : boolean;
procedure YY_INPUT(buf: out unbounded_character_array; result: out integer; max_size: in integer);
function yy_get_next_buffer return eob_action_type;
procedure yyunput( c : character; yy_bp: in out integer );
procedure unput(c : character);
function input return character;
procedure output(c : character);
function yywrap return boolean;
procedure Open_Input(fname : in String);
procedure Close_Input;
procedure Create_Output(fname : in String := "");
procedure Close_Output;
end ascan_io;
package body ascan_io is
-- gets input and stuffs it into 'buf'. number of characters read, or YY_NULL,
-- is returned in 'result'.
procedure YY_INPUT(buf: out unbounded_character_array; result: out integer; max_size: in integer) is
c : character;
i : integer := 1;
loc : integer := buf'first;
begin
while ( i <= max_size ) loop
if (end_of_line) then -- Ada ate our newline, put it back on the end.
buf(loc) := ASCII.LF;
skip_line(1);
else
get(buf(loc));
end if;
loc := loc + 1;
i := i + 1;
end loop;
result := i - 1;
exception
when END_ERROR => result := i - 1;
-- when we hit EOF we need to set yy_eof_has_been_seen
yy_eof_has_been_seen := true;
end YY_INPUT;
-- yy_get_next_buffer - try to read in new buffer
--
-- returns a code representing an action
-- EOB_ACT_LAST_MATCH -
-- EOB_ACT_RESTART_SCAN - restart the scanner
-- EOB_ACT_END_OF_FILE - end of file
function yy_get_next_buffer return eob_action_type is
dest : integer := 0;
source : integer := yytext_ptr - 1; -- copy prev. char, too
number_to_move : integer;
ret_val : eob_action_type;
num_to_read : integer;
begin
if ( yy_c_buf_p > yy_n_chars + 1 ) then
raise NULL_IN_INPUT;
end if;
-- try to read more data
-- first move last chars to start of buffer
number_to_move := yy_c_buf_p - yytext_ptr;
for i in 0..number_to_move - 1 loop
yy_ch_buf(dest) := yy_ch_buf(source);
dest := dest + 1;
source := source + 1;
end loop;
if ( yy_eof_has_been_seen ) then
-- don't do the read, it's not guaranteed to return an EOF,
-- just force an EOF
yy_n_chars := 0;
else
num_to_read := YY_BUF_SIZE - number_to_move - 1;
if ( num_to_read > YY_READ_BUF_SIZE ) then
num_to_read := YY_READ_BUF_SIZE;
end if;
-- read in more data
YY_INPUT( yy_ch_buf(number_to_move..yy_ch_buf'last), yy_n_chars, num_to_read );
end if;
if ( yy_n_chars = 0 ) then
if ( number_to_move = 1 ) then
ret_val := EOB_ACT_END_OF_FILE;
else
ret_val := EOB_ACT_LAST_MATCH;
end if;
yy_eof_has_been_seen := true;
else
ret_val := EOB_ACT_RESTART_SCAN;
end if;
yy_n_chars := yy_n_chars + number_to_move;
yy_ch_buf(yy_n_chars) := YY_END_OF_BUFFER_CHAR;
yy_ch_buf(yy_n_chars + 1) := YY_END_OF_BUFFER_CHAR;
-- yytext begins at the second character in
-- yy_ch_buf; the first character is the one which
-- preceded it before reading in the latest buffer;
-- it needs to be kept around in case it's a
-- newline, so yy_get_previous_state() will have
-- with '^' rules active
yytext_ptr := 1;
return ret_val;
end yy_get_next_buffer;
procedure yyunput( c : character; yy_bp: in out integer ) is
number_to_move : integer;
dest : integer;
source : integer;
tmp_yy_cp : integer;
begin
tmp_yy_cp := yy_c_buf_p;
yy_ch_buf(tmp_yy_cp) := yy_hold_char; -- undo effects of setting up yytext
if ( tmp_yy_cp < 2 ) then
-- need to shift things up to make room
number_to_move := yy_n_chars + 2; -- +2 for EOB chars
dest := YY_BUF_SIZE + 2;
source := number_to_move;
while ( source > 0 ) loop
dest := dest - 1;
source := source - 1;
yy_ch_buf(dest) := yy_ch_buf(source);
end loop;
tmp_yy_cp := tmp_yy_cp + dest - source;
yy_bp := yy_bp + dest - source;
yy_n_chars := YY_BUF_SIZE;
if ( tmp_yy_cp < 2 ) then
raise PUSHBACK_OVERFLOW;
end if;
end if;
if ( tmp_yy_cp > yy_bp and then yy_ch_buf(tmp_yy_cp-1) = ASCII.LF ) then
yy_ch_buf(tmp_yy_cp-2) := ASCII.LF;
end if;
tmp_yy_cp := tmp_yy_cp - 1;
yy_ch_buf(tmp_yy_cp) := c;
-- Note: this code is the text of YY_DO_BEFORE_ACTION, only
-- here we get different yy_cp and yy_bp's
yytext_ptr := yy_bp;
yy_hold_char := yy_ch_buf(tmp_yy_cp);
yy_ch_buf(tmp_yy_cp) := ASCII.NUL;
yy_c_buf_p := tmp_yy_cp;
end yyunput;
procedure unput(c : character) is
begin
yyunput( c, yy_bp );
end unput;
function input return character is
c : character;
yy_cp : integer := yy_c_buf_p;
begin
yy_ch_buf(yy_cp) := yy_hold_char;
if ( yy_ch_buf(yy_c_buf_p) = YY_END_OF_BUFFER_CHAR ) then
-- need more input
yytext_ptr := yy_c_buf_p;
yy_c_buf_p := yy_c_buf_p + 1;
case yy_get_next_buffer is
-- this code, unfortunately, is somewhat redundant with
-- that above
when EOB_ACT_END_OF_FILE =>
if ( yywrap ) then
yy_c_buf_p := yytext_ptr;
return ASCII.NUL;
end if;
yy_ch_buf(0) := ASCII.LF;
yy_n_chars := 1;
yy_ch_buf(yy_n_chars) := YY_END_OF_BUFFER_CHAR;
yy_ch_buf(yy_n_chars + 1) := YY_END_OF_BUFFER_CHAR;
yy_eof_has_been_seen := false;
yy_c_buf_p := 1;
yytext_ptr := yy_c_buf_p;
yy_hold_char := yy_ch_buf(yy_c_buf_p);
return ( input );
when EOB_ACT_RESTART_SCAN =>
yy_c_buf_p := yytext_ptr;
when EOB_ACT_LAST_MATCH =>
raise UNEXPECTED_LAST_MATCH;
when others => null;
end case;
end if;
c := yy_ch_buf(yy_c_buf_p);
yy_c_buf_p := yy_c_buf_p + 1;
yy_hold_char := yy_ch_buf(yy_c_buf_p);
return c;
end input;
procedure output(c : character) is
begin
text_io.put(c);
end output;
-- default yywrap function - always treat EOF as an EOF
function yywrap return boolean is
begin
return true;
end yywrap;
procedure Open_Input(fname : in String) is
f : file_type;
begin
yy_init := true;
open(f, in_file, fname);
set_input(f);
end Open_Input;
procedure Create_Output(fname : in String := "") is
f : file_type;
begin
if (fname /= "") then
create(f, out_file, fname);
set_output(f);
end if;
end Create_Output;
procedure Close_Input is
begin
null;
end Close_Input;
procedure Close_Output is
begin
null;
end Close_Output;
end ascan_io;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE character classes routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION routines for character classes like [abc]
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/cclB.a,v 1.5 90/01/12 15:19:40 self Exp Locker: self $
with MISC_DEFS, TEXT_IO, MISC, TSTRING; use MISC_DEFS, TEXT_IO;
package body CCL is
-- ccladd - add a single character to a ccl
procedure CCLADD(CCLP : in INTEGER;
CH : in CHARACTER) is
IND, LEN, NEWPOS : INTEGER;
begin
LEN := CCLLEN(CCLP);
IND := CCLMAP(CCLP);
-- check to see if the character is already in the ccl
for I in 0 .. LEN - 1 loop
if (CCLTBL(IND + I) = CH) then
return;
end if;
end loop;
NEWPOS := IND + LEN;
if (NEWPOS >= CURRENT_MAX_CCL_TBL_SIZE) then
CURRENT_MAX_CCL_TBL_SIZE := CURRENT_MAX_CCL_TBL_SIZE +
MAX_CCL_TBL_SIZE_INCREMENT;
NUM_REALLOCS := NUM_REALLOCS + 1;
REALLOCATE_CHARACTER_ARRAY(CCLTBL, CURRENT_MAX_CCL_TBL_SIZE);
end if;
CCLLEN(CCLP) := LEN + 1;
CCLTBL(NEWPOS) := CH;
end CCLADD;
-- cclinit - make an empty ccl
function CCLINIT return INTEGER is
begin
LASTCCL := LASTCCL + 1;
if (LASTCCL >= CURRENT_MAXCCLS) then
CURRENT_MAXCCLS := CURRENT_MAXCCLS + MAX_CCLS_INCREMENT;
NUM_REALLOCS := NUM_REALLOCS + 1;
REALLOCATE_INTEGER_ARRAY(CCLMAP, CURRENT_MAXCCLS);
REALLOCATE_INTEGER_ARRAY(CCLLEN, CURRENT_MAXCCLS);
REALLOCATE_INTEGER_ARRAY(CCLNG, CURRENT_MAXCCLS);
end if;
if (LASTCCL = 1) then
-- we're making the first ccl
CCLMAP(LASTCCL) := 0;
else
-- the new pointer is just past the end of the last ccl. Since
-- the cclmap points to the \first/ character of a ccl, adding the
-- length of the ccl to the cclmap pointer will produce a cursor
-- to the first free space
CCLMAP(LASTCCL) := CCLMAP(LASTCCL - 1) + CCLLEN(LASTCCL - 1);
end if;
CCLLEN(LASTCCL) := 0;
CCLNG(LASTCCL) := 0;
-- ccl's start out life un-negated
return LASTCCL;
end CCLINIT;
-- cclnegate - negate a ccl
procedure CCLNEGATE(CCLP : in INTEGER) is
begin
CCLNG(CCLP) := 1;
end CCLNEGATE;
-- list_character_set - list the members of a set of characters in CCL form
--
-- writes to the given file a character-class representation of those
-- characters present in the given set. A character is present if it
-- has a non-zero value in the set array.
procedure LIST_CHARACTER_SET(F : in FILE_TYPE;
CSET : in C_SIZE_BOOL_ARRAY) is
I, START_CHAR : INTEGER;
begin
TEXT_IO.PUT(F, '[');
I := 1;
while (I <= CSIZE) loop
if (CSET(I)) then
START_CHAR := I;
TEXT_IO.PUT(F, ' ');
TSTRING.PUT(F, MISC.READABLE_FORM(CHARACTER'VAL(I)));
I := I + 1;
while ((I <= CSIZE) and then (CSET(I))) loop
I := I + 1;
end loop;
if (I - 1 > START_CHAR) then
-- this was a run
TEXT_IO.PUT(F, "-");
TSTRING.PUT(MISC.READABLE_FORM(CHARACTER'VAL(I - 1)));
end if;
TEXT_IO.PUT(F, ' ');
end if;
I := I + 1;
end loop;
TEXT_IO.PUT(F, ']');
end LIST_CHARACTER_SET;
end CCL;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE character classes routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION routines for character classes like [abc]
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/cclS.a,v 1.3 90/01/12 15:19:43 self Exp Locker: self $
with MISC_DEFS, TEXT_IO; use MISC_DEFS, TEXT_IO;
package CCL is
procedure CCLADD(CCLP : in INTEGER;
CH : in CHARACTER);
function CCLINIT return INTEGER;
procedure CCLNEGATE(CCLP : in INTEGER);
procedure LIST_CHARACTER_SET(F : in FILE_TYPE;
CSET : in C_SIZE_BOOL_ARRAY);
end CCL;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE command line interface
-- AUTHOR: John Self (UCI)
-- DESCRIPTION command line interface body for use with the VERDIX VADS system.
-- NOTES this file is system dependent
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/command_lineB.a,v 1.3 90/01/12 15:19:44 self Exp Locker: self $
with TSTRING; use TSTRING;
with A_STRINGS; use A_STRINGS;
with COMMAND_LINE;
package body COMMAND_LINE_INTERFACE is
procedure INITIALIZE_COMMAND_LINE is
begin
for I in 0 .. COMMAND_LINE.ARGC - 1 loop
ARGV(I) := VSTR(COMMAND_LINE.ARGV(I).S);
end loop;
ARGC := COMMAND_LINE.ARGC;
end INITIALIZE_COMMAND_LINE;
end COMMAND_LINE_INTERFACE;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE command line interface
-- AUTHOR: John Self (UCI)
-- DESCRIPTION command line interface body for use with the VERDIX VADS system.
-- NOTES this file is system dependent
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/command_lineS.a,v 1.3 90/01/12 15:19:46 self Exp Locker: self $
with TSTRING; use TSTRING;
package COMMAND_LINE_INTERFACE is
MAX_NUMBER_ARGS : INTEGER := 32;
type COMMAND_VECTOR is array(0 .. MAX_NUMBER_ARGS) of VSTRING;
procedure INITIALIZE_COMMAND_LINE;
ARGV : COMMAND_VECTOR;
ARGC : INTEGER;
end COMMAND_LINE_INTERFACE;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE DFA construction routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION converts non-deterministic finite automatons to finite ones.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/dfaB.a,v 1.18 90/01/12 15:19:48 self Exp Locker: self $
with DFA, INT_IO, MISC_DEFS, TEXT_IO, MISC, TBLCMP, CCL, EXTERNAL_FILE_MANAGER;
with ECS, NFA, TSTRING, GEN, SKELETON_MANAGER; use MISC_DEFS,
EXTERNAL_FILE_MANAGER;
package body DFA is
use TSTRING;
-- check_for_backtracking - check a DFA state for backtracking
--
-- ds is the number of the state to check and state[) is its out-transitions,
-- indexed by equivalence class, and state_rules[) is the set of rules
-- associated with this state
DID_STK_INIT : BOOLEAN := FALSE;
STK : INT_PTR;
procedure CHECK_FOR_BACKTRACKING(DS : in INTEGER;
STATE : in UNBOUNDED_INT_ARRAY) is
use MISC_DEFS;
begin
if (DFAACC(DS).DFAACC_STATE = 0) then
-- state is non-accepting
NUM_BACKTRACKING := NUM_BACKTRACKING + 1;
if (BACKTRACK_REPORT) then
TEXT_IO.PUT(BACKTRACK_FILE, "State #");
INT_IO.PUT(BACKTRACK_FILE, DS, 1);
TEXT_IO.PUT(BACKTRACK_FILE, "is non-accepting -");
TEXT_IO.NEW_LINE(BACKTRACK_FILE);
-- identify the state
DUMP_ASSOCIATED_RULES(BACKTRACK_FILE, DS);
-- now identify it further using the out- and jam-transitions
DUMP_TRANSITIONS(BACKTRACK_FILE, STATE);
TEXT_IO.NEW_LINE(BACKTRACK_FILE);
end if;
end if;
end CHECK_FOR_BACKTRACKING;
-- check_trailing_context - check to see if NFA state set constitutes
-- "dangerous" trailing context
--
-- NOTES
-- Trailing context is "dangerous" if both the head and the trailing
-- part are of variable size \and/ there's a DFA state which contains
-- both an accepting state for the head part of the rule and NFA states
-- which occur after the beginning of the trailing context.
-- When such a rule is matched, it's impossible to tell if having been
-- in the DFA state indicates the beginning of the trailing context
-- or further-along scanning of the pattern. In these cases, a warning
-- message is issued.
--
-- nfa_states[1 .. num_states) is the list of NFA states in the DFA.
-- accset[1 .. nacc) is the list of accepting numbers for the DFA state.
procedure CHECK_TRAILING_CONTEXT(NFA_STATES : in INT_PTR;
NUM_STATES : in INTEGER;
ACCSET : in INT_PTR;
NACC : in INTEGER) is
NS, AR : INTEGER;
STATE_VAR, TYPE_VAR : STATE_ENUM;
use MISC_DEFS, MISC, TEXT_IO;
begin
for I in 1 .. NUM_STATES loop
NS := NFA_STATES(I);
TYPE_VAR := STATE_TYPE(NS);
AR := ASSOC_RULE(NS);
if ((TYPE_VAR = STATE_NORMAL) or (RULE_TYPE(AR) /= RULE_VARIABLE)) then
null;
-- do nothing
else
if (TYPE_VAR = STATE_TRAILING_CONTEXT) then
-- potential trouble. Scan set of accepting numbers for
-- the one marking the end of the "head". We assume that
-- this looping will be fairly cheap since it's rare that
-- an accepting number set is large.
for J in 1 .. NACC loop
if (CHECK_YY_TRAILING_HEAD_MASK(ACCSET(J)) /= 0) then
TEXT_IO.PUT(STANDARD_ERROR,
"aflex: Dangerous trailing context in rule at line ");
INT_IO.PUT(STANDARD_ERROR, RULE_LINENUM(AR), 1);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
return;
end if;
end loop;
end if;
end if;
end loop;
end CHECK_TRAILING_CONTEXT;
-- dump_associated_rules - list the rules associated with a DFA state
--
-- goes through the set of NFA states associated with the DFA and
-- extracts the first MAX_ASSOC_RULES unique rules, sorts them,
-- and writes a report to the given file
procedure DUMP_ASSOCIATED_RULES(F : in FILE_TYPE;
DS : in INTEGER) is
J : INTEGER;
NUM_ASSOCIATED_RULES : INTEGER := 0;
RULE_SET : INT_PTR;
SIZE, RULE_NUM : INTEGER;
begin
RULE_SET := new UNBOUNDED_INT_ARRAY(0 .. MAX_ASSOC_RULES + 1);
SIZE := DFASIZ(DS);
for I in 1 .. SIZE loop
RULE_NUM := RULE_LINENUM(ASSOC_RULE(DSS(DS)(I)));
J := 1;
while (J <= NUM_ASSOCIATED_RULES) loop
if (RULE_NUM = RULE_SET(J)) then
exit;
end if;
J := J + 1;
end loop;
if (J > NUM_ASSOCIATED_RULES) then
--new rule
if (NUM_ASSOCIATED_RULES < MAX_ASSOC_RULES) then
NUM_ASSOCIATED_RULES := NUM_ASSOCIATED_RULES + 1;
RULE_SET(NUM_ASSOCIATED_RULES) := RULE_NUM;
end if;
end if;
end loop;
MISC.BUBBLE(RULE_SET, NUM_ASSOCIATED_RULES);
TEXT_IO.PUT(F, " associated rules:");
for I in 1 .. NUM_ASSOCIATED_RULES loop
if (I mod 8 = 1) then
TEXT_IO.NEW_LINE(F);
end if;
TEXT_IO.PUT(F, ASCII.HT);
INT_IO.PUT(F, RULE_SET(I), 1);
end loop;
TEXT_IO.NEW_LINE(F);
exception
when STORAGE_ERROR =>
MISC.AFLEXFATAL("dynamic memory failure in dump_associated_rules()");
end DUMP_ASSOCIATED_RULES;
-- dump_transitions - list the transitions associated with a DFA state
--
-- goes through the set of out-transitions and lists them in human-readable
-- form (i.e., not as equivalence classes); also lists jam transitions
-- (i.e., all those which are not out-transitions, plus EOF). The dump
-- is done to the given file.
procedure DUMP_TRANSITIONS(F : in FILE_TYPE;
STATE : in UNBOUNDED_INT_ARRAY) is
EC : INTEGER;
OUT_CHAR_SET : C_SIZE_BOOL_ARRAY;
begin
for I in 1 .. CSIZE loop
EC := ECGROUP(I);
if (EC < 0) then
EC := -EC;
end if;
OUT_CHAR_SET(I) := (STATE(EC) /= 0);
end loop;
TEXT_IO.PUT(F, " out-transitions: ");
CCL.LIST_CHARACTER_SET(F, OUT_CHAR_SET);
-- now invert the members of the set to get the jam transitions
for I in 1 .. CSIZE loop
OUT_CHAR_SET(I) := not OUT_CHAR_SET(I);
end loop;
TEXT_IO.NEW_LINE(F);
TEXT_IO.PUT(F, "jam-transitions: EOF ");
CCL.LIST_CHARACTER_SET(F, OUT_CHAR_SET);
TEXT_IO.NEW_LINE(F);
end DUMP_TRANSITIONS;
-- epsclosure - construct the epsilon closure of a set of ndfa states
--
-- NOTES
-- the epsilon closure is the set of all states reachable by an arbitrary
-- number of epsilon transitions which themselves do not have epsilon
-- transitions going out, unioned with the set of states which have non-null
-- accepting numbers. t is an array of size numstates of nfa state numbers.
-- Upon return, t holds the epsilon closure and numstates is updated. accset
-- holds a list of the accepting numbers, and the size of accset is given
-- by nacc. t may be subjected to reallocation if it is not large enough
-- to hold the epsilon closure.
--
-- hashval is the hash value for the dfa corresponding to the state set
procedure EPSCLOSURE(T : in out INT_PTR;
NS_ADDR : in out INTEGER;
ACCSET : in out INT_PTR;
NACC_ADDR, HV_ADDR : out INTEGER;
RESULT : out INT_PTR) is
NS, TSP : INTEGER;
NUMSTATES, NACC, HASHVAL, TRANSSYM, NFACCNUM : INTEGER;
STKEND : INTEGER;
STKPOS : INTEGER;
procedure MARK_STATE(STATE : in INTEGER) is
begin
TRANS1(STATE) := TRANS1(STATE) - MARKER_DIFFERENCE;
end MARK_STATE;
pragma INLINE(MARK_STATE);
function IS_MARKED(STATE : in INTEGER) return BOOLEAN is
begin
return TRANS1(STATE) < 0;
end IS_MARKED;
pragma INLINE(IS_MARKED);
procedure UNMARK_STATE(STATE : in INTEGER) is
begin
TRANS1(STATE) := TRANS1(STATE) + MARKER_DIFFERENCE;
end UNMARK_STATE;
pragma INLINE(UNMARK_STATE);
procedure CHECK_ACCEPT(STATE : in INTEGER) is
begin
NFACCNUM := ACCPTNUM(STATE);
if (NFACCNUM /= NIL) then
NACC := NACC + 1;
ACCSET(NACC) := NFACCNUM;
end if;
end CHECK_ACCEPT;
pragma INLINE(CHECK_ACCEPT);
procedure DO_REALLOCATION is
begin
CURRENT_MAX_DFA_SIZE := CURRENT_MAX_DFA_SIZE + MAX_DFA_SIZE_INCREMENT;
NUM_REALLOCS := NUM_REALLOCS + 1;
REALLOCATE_INTEGER_ARRAY(T, CURRENT_MAX_DFA_SIZE);
REALLOCATE_INTEGER_ARRAY(STK, CURRENT_MAX_DFA_SIZE);
end DO_REALLOCATION;
pragma INLINE(DO_REALLOCATION);
procedure PUT_ON_STACK(STATE : in INTEGER) is
begin
STKEND := STKEND + 1;
if (STKEND >= CURRENT_MAX_DFA_SIZE) then
DO_REALLOCATION;
end if;
STK(STKEND) := STATE;
MARK_STATE(STATE);
end PUT_ON_STACK;
pragma INLINE(PUT_ON_STACK);
procedure ADD_STATE(STATE : in INTEGER) is
begin
NUMSTATES := NUMSTATES + 1;
if (NUMSTATES >= CURRENT_MAX_DFA_SIZE) then
DO_REALLOCATION;
end if;
T(NUMSTATES) := STATE;
HASHVAL := HASHVAL + STATE;
end ADD_STATE;
pragma INLINE(ADD_STATE);
procedure STACK_STATE(STATE : in INTEGER) is
begin
PUT_ON_STACK(STATE);
CHECK_ACCEPT(STATE);
if ((NFACCNUM /= NIL) or (TRANSCHAR(STATE) /= SYM_EPSILON)) then
ADD_STATE(STATE);
end if;
end STACK_STATE;
pragma INLINE(STACK_STATE);
begin
NUMSTATES := NS_ADDR;
if (not DID_STK_INIT) then
STK := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_DFA_SIZE);
DID_STK_INIT := TRUE;
end if;
NACC := 0;
STKEND := 0;
HASHVAL := 0;
for NSTATE in 1 .. NUMSTATES loop
NS := T(NSTATE);
-- the state could be marked if we've already pushed it onto
-- the stack
if (not IS_MARKED(NS)) then
PUT_ON_STACK(NS);
null;
end if;
CHECK_ACCEPT(NS);
HASHVAL := HASHVAL + NS;
end loop;
STKPOS := 1;
while (STKPOS <= STKEND) loop
NS := STK(STKPOS);
TRANSSYM := TRANSCHAR(NS);
if (TRANSSYM = SYM_EPSILON) then
TSP := TRANS1(NS) + MARKER_DIFFERENCE;
if (TSP /= NO_TRANSITION) then
if (not IS_MARKED(TSP)) then
STACK_STATE(TSP);
end if;
TSP := TRANS2(NS);
if (TSP /= NO_TRANSITION) then
if (not IS_MARKED(TSP)) then
STACK_STATE(TSP);
end if;
end if;
end if;
end if;
STKPOS := STKPOS + 1;
end loop;
-- clear out "visit" markers
for CHK_STKPOS in 1 .. STKEND loop
if (IS_MARKED(STK(CHK_STKPOS))) then
UNMARK_STATE(STK(CHK_STKPOS));
else
MISC.AFLEXFATAL("consistency check failed in epsclosure()");
end if;
end loop;
NS_ADDR := NUMSTATES;
HV_ADDR := HASHVAL;
NACC_ADDR := NACC;
RESULT := T;
end EPSCLOSURE;
-- increase_max_dfas - increase the maximum number of DFAs
procedure INCREASE_MAX_DFAS is
begin
CURRENT_MAX_DFAS := CURRENT_MAX_DFAS + MAX_DFAS_INCREMENT;
NUM_REALLOCS := NUM_REALLOCS + 1;
REALLOCATE_INTEGER_ARRAY(BASE, CURRENT_MAX_DFAS);
REALLOCATE_INTEGER_ARRAY(DEF, CURRENT_MAX_DFAS);
REALLOCATE_INTEGER_ARRAY(DFASIZ, CURRENT_MAX_DFAS);
REALLOCATE_INTEGER_ARRAY(ACCSIZ, CURRENT_MAX_DFAS);
REALLOCATE_INTEGER_ARRAY(DHASH, CURRENT_MAX_DFAS);
REALLOCATE_INT_PTR_ARRAY(DSS, CURRENT_MAX_DFAS);
REALLOCATE_DFAACC_UNION(DFAACC, CURRENT_MAX_DFAS);
end INCREASE_MAX_DFAS;
-- ntod - convert an ndfa to a dfa
--
-- creates the dfa corresponding to the ndfa we've constructed. the
-- dfa starts out in state #1.
procedure NTOD is
ACCSET : INT_PTR;
DS, NACC, NEWDS : INTEGER;
DUPLIST, TARGFREQ, TARGSTATE, STATE : C_SIZE_ARRAY;
SYMLIST : C_SIZE_BOOL_ARRAY;
HASHVAL, NUMSTATES, DSIZE : INTEGER;
NSET, DSET : INT_PTR;
TARGPTR, TOTALTRANS, I, J, COMSTATE, COMFREQ, TARG : INTEGER;
NUM_START_STATES, TODO_HEAD, TODO_NEXT : INTEGER;
SNSRESULT : BOOLEAN;
FULL_TABLE_TEMP_FILE : FILE_TYPE;
BUF : VSTRING;
NUM_NXT_STATES : INTEGER;
use TEXT_IO;
-- this is so find_table_space(...) will know where to start looking in
-- chk/nxt for unused records for space to put in the state
begin
ACCSET := ALLOCATE_INTEGER_ARRAY(NUM_RULES + 1);
NSET := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_DFA_SIZE);
-- the "todo" queue is represented by the head, which is the DFA
-- state currently being processed, and the "next", which is the
-- next DFA state number available (not in use). We depend on the
-- fact that snstods() returns DFA's \in increasing order/, and thus
-- need only know the bounds of the dfas to be processed.
TODO_HEAD := 0;
TODO_NEXT := 0;
for CNT in 0 .. CSIZE loop
DUPLIST(CNT) := NIL;
SYMLIST(CNT) := FALSE;
end loop;
for CNT in 0 .. NUM_RULES loop
ACCSET(CNT) := NIL;
end loop;
if (TRACE) then
NFA.DUMPNFA(SCSET(1));
TEXT_IO.NEW_LINE(STANDARD_ERROR);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
TEXT_IO.PUT(STANDARD_ERROR, "DFA Dump:");
TEXT_IO.NEW_LINE(STANDARD_ERROR);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
end if;
TBLCMP.INITTBL;
if (FULLTBL) then
GEN.DO_SECT3_OUT;
-- output user code up to ##
SKELETON_MANAGER.SKELOUT;
-- declare it "short" because it's a real long-shot that that
-- won't be large enough
begin -- make a temporary file to write yy_nxt array into
CREATE(FULL_TABLE_TEMP_FILE, OUT_FILE);
exception
when USE_ERROR | NAME_ERROR =>
MISC.AFLEXFATAL("can't create temporary file");
end;
NUM_NXT_STATES := 1;
TEXT_IO.PUT(FULL_TABLE_TEMP_FILE, "( ");
-- generate 0 entries for state #0
for CNT in 0 .. NUMECS loop
MISC.MK2DATA(FULL_TABLE_TEMP_FILE, 0);
end loop;
TEXT_IO.PUT(FULL_TABLE_TEMP_FILE, " )");
-- force extra blank line next dataflush()
DATALINE := NUMDATALINES;
end if;
-- create the first states
NUM_START_STATES := LASTSC*2;
for CNT in 1 .. NUM_START_STATES loop
NUMSTATES := 1;
-- for each start condition, make one state for the case when
-- we're at the beginning of the line (the '%' operator) and
-- one for the case when we're not
if (CNT mod 2 = 1) then
NSET(NUMSTATES) := SCSET((CNT/2) + 1);
else
NSET(NUMSTATES) := NFA.MKBRANCH(SCBOL(CNT/2), SCSET(CNT/2));
end if;
DFA.EPSCLOSURE(NSET, NUMSTATES, ACCSET, NACC, HASHVAL, NSET);
SNSTODS(NSET, NUMSTATES, ACCSET, NACC, HASHVAL, DS, SNSRESULT);
if (SNSRESULT) then
NUMAS := NUMAS + NACC;
TOTNST := TOTNST + NUMSTATES;
TODO_NEXT := TODO_NEXT + 1;
if (VARIABLE_TRAILING_CONTEXT_RULES and (NACC > 0)) then
CHECK_TRAILING_CONTEXT(NSET, NUMSTATES, ACCSET, NACC);
end if;
end if;
end loop;
SNSTODS(NSET, 0, ACCSET, 0, 0, END_OF_BUFFER_STATE, SNSRESULT);
if (not SNSRESULT) then
MISC.AFLEXFATAL("could not create unique end-of-buffer state");
end if;
NUMAS := NUMAS + 1;
NUM_START_STATES := NUM_START_STATES + 1;
TODO_NEXT := TODO_NEXT + 1;
while (TODO_HEAD < TODO_NEXT) loop
NUM_NXT_STATES := NUM_NXT_STATES + 1;
TARGPTR := 0;
TOTALTRANS := 0;
for STATE_CNT in 1 .. NUMECS loop
STATE(STATE_CNT) := 0;
end loop;
TODO_HEAD := TODO_HEAD + 1;
DS := TODO_HEAD;
DSET := DSS(DS);
DSIZE := DFASIZ(DS);
if (TRACE) then
TEXT_IO.PUT(STANDARD_ERROR, "state # ");
INT_IO.PUT(STANDARD_ERROR, DS, 1);
TEXT_IO.PUT_LINE(STANDARD_ERROR, ":");
end if;
SYMPARTITION(DSET, DSIZE, SYMLIST, DUPLIST);
for SYM in 1 .. NUMECS loop
if (SYMLIST(SYM)) then
SYMLIST(SYM) := FALSE;
if (DUPLIST(SYM) = NIL) then
-- symbol has unique out-transitions
NUMSTATES := SYMFOLLOWSET(DSET, DSIZE, SYM, NSET);
DFA.EPSCLOSURE(NSET, NUMSTATES, ACCSET, NACC, HASHVAL, NSET);
SNSTODS(NSET, NUMSTATES, ACCSET, NACC, HASHVAL, NEWDS, SNSRESULT);
if (SNSRESULT) then
TOTNST := TOTNST + NUMSTATES;
TODO_NEXT := TODO_NEXT + 1;
NUMAS := NUMAS + NACC;
if (VARIABLE_TRAILING_CONTEXT_RULES and (NACC > 0)) then
CHECK_TRAILING_CONTEXT(NSET, NUMSTATES, ACCSET, NACC);
end if;
end if;
STATE(SYM) := NEWDS;
if (TRACE) then
TEXT_IO.PUT(STANDARD_ERROR, ASCII.HT);
INT_IO.PUT(STANDARD_ERROR, SYM, 1);
TEXT_IO.PUT(STANDARD_ERROR, ASCII.HT);
INT_IO.PUT(STANDARD_ERROR, NEWDS, 1);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
end if;
TARGPTR := TARGPTR + 1;
TARGFREQ(TARGPTR) := 1;
TARGSTATE(TARGPTR) := NEWDS;
NUMUNIQ := NUMUNIQ + 1;
else
-- sym's equivalence class has the same transitions
-- as duplist(sym)'s equivalence class
TARG := STATE(DUPLIST(SYM));
STATE(SYM) := TARG;
if (TRACE) then
TEXT_IO.PUT(STANDARD_ERROR, ASCII.HT);
INT_IO.PUT(STANDARD_ERROR, SYM, 1);
TEXT_IO.PUT(STANDARD_ERROR, ASCII.HT);
INT_IO.PUT(STANDARD_ERROR, TARG, 1);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
end if;
-- update frequency count for destination state
I := 1;
while (TARGSTATE(I) /= TARG) loop
I := I + 1;
end loop;
TARGFREQ(I) := TARGFREQ(I) + 1;
NUMDUP := NUMDUP + 1;
end if;
TOTALTRANS := TOTALTRANS + 1;
DUPLIST(SYM) := NIL;
end if;
end loop;
NUMSNPAIRS := NUMSNPAIRS + TOTALTRANS;
if (CASEINS and not USEECS) then
I := CHARACTER'POS('A');
J := CHARACTER'POS('a');
while (I < CHARACTER'POS('Z')) loop
STATE(I) := STATE(J);
I := I + 1;
J := J + 1;
end loop;
end if;
if (DS > NUM_START_STATES) then
CHECK_FOR_BACKTRACKING(DS, STATE);
end if;
if (FULLTBL) then
-- supply array's 0-element
TEXT_IO.PUT(FULL_TABLE_TEMP_FILE, ",");
MISC.DATAFLUSH(FULL_TABLE_TEMP_FILE);
TEXT_IO.PUT(FULL_TABLE_TEMP_FILE, "( ");
if (DS = END_OF_BUFFER_STATE) then
MISC.MK2DATA(FULL_TABLE_TEMP_FILE, -END_OF_BUFFER_STATE);
else
MISC.MK2DATA(FULL_TABLE_TEMP_FILE, END_OF_BUFFER_STATE);
end if;
for CNT in 1 .. NUMECS loop
-- jams are marked by negative of state number
if ((STATE(CNT) /= 0)) then
MISC.MK2DATA(FULL_TABLE_TEMP_FILE, STATE(CNT));
else
MISC.MK2DATA(FULL_TABLE_TEMP_FILE, -DS);
end if;
end loop;
TEXT_IO.PUT(FULL_TABLE_TEMP_FILE, " )");
-- force extra blank line next dataflush()
DATALINE := NUMDATALINES;
else
if (DS = END_OF_BUFFER_STATE) then
-- special case this state to make sure it does what it's
-- supposed to, i.e., jam on end-of-buffer
TBLCMP.STACK1(DS, 0, 0, JAMSTATE_CONST);
else -- normal, compressed state
-- determine which destination state is the most common, and
-- how many transitions to it there are
COMFREQ := 0;
COMSTATE := 0;
for CNT in 1 .. TARGPTR loop
if (TARGFREQ(CNT) > COMFREQ) then
COMFREQ := TARGFREQ(CNT);
COMSTATE := TARGSTATE(CNT);
end if;
end loop;
TBLCMP.BLDTBL(STATE, DS, TOTALTRANS, COMSTATE, COMFREQ);
end if;
end if;
end loop;
if (FULLTBL) then
TEXT_IO.PUT("yy_nxt : constant array(0..");
INT_IO.PUT(NUM_NXT_STATES - 1, 1);
TEXT_IO.PUT_LINE(" , character'first..character'last) of short :=");
TEXT_IO.PUT_LINE(" (");
RESET(FULL_TABLE_TEMP_FILE, IN_FILE);
while (not END_OF_FILE(FULL_TABLE_TEMP_FILE)) loop
TSTRING.GET_LINE(FULL_TABLE_TEMP_FILE, BUF);
TSTRING.PUT_LINE(BUF);
end loop;
DELETE(FULL_TABLE_TEMP_FILE);
MISC.DATAEND;
else
TBLCMP.CMPTMPS; -- create compressed template entries
-- create tables for all the states with only one out-transition
while (ONESP > 0) loop
TBLCMP.MK1TBL(ONESTATE(ONESP), ONESYM(ONESP), ONENEXT(ONESP), ONEDEF(
ONESP));
ONESP := ONESP - 1;
end loop;
TBLCMP.MKDEFTBL;
end if;
end NTOD;
-- snstods - converts a set of ndfa states into a dfa state
--
-- on return, the dfa state number is in newds.
procedure SNSTODS(SNS : in INT_PTR;
NUMSTATES : in INTEGER;
ACCSET : in INT_PTR;
NACC, HASHVAL : in INTEGER;
NEWDS_ADDR : out INTEGER;
RESULT : out BOOLEAN) is
DIDSORT : BOOLEAN := FALSE;
J : INTEGER;
NEWDS : INTEGER;
OLDSNS : INT_PTR;
begin
for I in 1 .. LASTDFA loop
if (HASHVAL = DHASH(I)) then
if (NUMSTATES = DFASIZ(I)) then
OLDSNS := DSS(I);
if (not DIDSORT) then
-- we sort the states in sns so we can compare it to
-- oldsns quickly. we use bubble because there probably
-- aren't very many states
MISC.BUBBLE(SNS, NUMSTATES);
DIDSORT := TRUE;
end if;
J := 1;
while (J <= NUMSTATES) loop
if (SNS(J) /= OLDSNS(J)) then
exit;
end if;
J := J + 1;
end loop;
if (J > NUMSTATES) then
DFAEQL := DFAEQL + 1;
NEWDS_ADDR := I;
RESULT := FALSE;
return;
end if;
HSHCOL := HSHCOL + 1;
else
HSHSAVE := HSHSAVE + 1;
end if;
end if;
end loop;
-- make a new dfa
LASTDFA := LASTDFA + 1;
if (LASTDFA >= CURRENT_MAX_DFAS) then
INCREASE_MAX_DFAS;
end if;
NEWDS := LASTDFA;
DSS(NEWDS) := new UNBOUNDED_INT_ARRAY(0 .. NUMSTATES + 1);
-- if we haven't already sorted the states in sns, we do so now, so that
-- future comparisons with it can be made quickly
if (not DIDSORT) then
MISC.BUBBLE(SNS, NUMSTATES);
end if;
for I in 1 .. NUMSTATES loop
DSS(NEWDS)(I) := SNS(I);
end loop;
DFASIZ(NEWDS) := NUMSTATES;
DHASH(NEWDS) := HASHVAL;
if (NACC = 0) then
DFAACC(NEWDS).DFAACC_STATE := 0;
ACCSIZ(NEWDS) := 0;
else
-- find lowest numbered rule so the disambiguating rule will work
J := NUM_RULES + 1;
for I in 1 .. NACC loop
if (ACCSET(I) < J) then
J := ACCSET(I);
end if;
end loop;
DFAACC(NEWDS).DFAACC_STATE := J;
end if;
NEWDS_ADDR := NEWDS;
RESULT := TRUE;
return;
exception
when STORAGE_ERROR =>
MISC.AFLEXFATAL("dynamic memory failure in snstods()");
end SNSTODS;
-- symfollowset - follow the symbol transitions one step
function SYMFOLLOWSET(DS : in INT_PTR;
DSIZE, TRANSSYM : in INTEGER;
NSET : in INT_PTR) return INTEGER is
NS, TSP, SYM, LENCCL, CH, NUMSTATES, CCLLIST : INTEGER;
begin
NUMSTATES := 0;
for I in 1 .. DSIZE loop
-- for each nfa state ns in the state set of ds
NS := DS(I);
SYM := TRANSCHAR(NS);
TSP := TRANS1(NS);
if (SYM < 0) then
-- it's a character class
SYM := -SYM;
CCLLIST := CCLMAP(SYM);
LENCCL := CCLLEN(SYM);
if (CCLNG(SYM) /= 0) then
for J in 0 .. LENCCL - 1 loop
-- loop through negated character class
CH := CHARACTER'POS(CCLTBL(CCLLIST + J));
if (CH > TRANSSYM) then
exit; -- transsym isn't in negated ccl
else
if (CH = TRANSSYM) then
goto BOTTOM; -- next 2
end if;
end if;
end loop;
-- didn't find transsym in ccl
NUMSTATES := NUMSTATES + 1;
NSET(NUMSTATES) := TSP;
else
for J in 0 .. LENCCL - 1 loop
CH := CHARACTER'POS(CCLTBL(CCLLIST + J));
if (CH > TRANSSYM) then
exit;
else
if (CH = TRANSSYM) then
NUMSTATES := NUMSTATES + 1;
NSET(NUMSTATES) := TSP;
exit;
end if;
end if;
end loop;
end if;
else
if ((SYM >= CHARACTER'POS('A')) and (SYM <= CHARACTER'POS('Z')) and
CASEINS) then
MISC.AFLEXFATAL("consistency check failed in symfollowset");
else
if (SYM = SYM_EPSILON) then
null; -- do nothing
else
if (ECGROUP(SYM) = TRANSSYM) then
NUMSTATES := NUMSTATES + 1;
NSET(NUMSTATES) := TSP;
end if;
end if;
end if;
end if;
<<BOTTOM>> null;
end loop;
return NUMSTATES;
end SYMFOLLOWSET;
-- sympartition - partition characters with same out-transitions
procedure SYMPARTITION(DS : in INT_PTR;
NUMSTATES : in INTEGER;
SYMLIST : in out C_SIZE_BOOL_ARRAY;
DUPLIST : in out C_SIZE_ARRAY) is
TCH, J, NS, LENCCL, CCLP, ICH : INTEGER;
DUPFWD : C_SIZE_ARRAY;
-- partitioning is done by creating equivalence classes for those
-- characters which have out-transitions from the given state. Thus
-- we are really creating equivalence classes of equivalence classes.
begin
for I in 1 .. NUMECS loop
-- initialize equivalence class list
DUPLIST(I) := I - 1;
DUPFWD(I) := I + 1;
end loop;
DUPLIST(1) := NIL;
DUPFWD(NUMECS) := NIL;
DUPFWD(0) := 0;
for I in 1 .. NUMSTATES loop
NS := DS(I);
TCH := TRANSCHAR(NS);
if (TCH /= SYM_EPSILON) then
if ((TCH < -LASTCCL) or (TCH > CSIZE)) then
MISC.AFLEXFATAL("bad transition character detected in sympartition()")
;
end if;
if (TCH > 0) then
-- character transition
ECS.MKECHAR(ECGROUP(TCH), DUPFWD, DUPLIST);
SYMLIST(ECGROUP(TCH)) := TRUE;
else
-- character class
TCH := -TCH;
LENCCL := CCLLEN(TCH);
CCLP := CCLMAP(TCH);
ECS.MKECCL(CCLTBL(CCLP .. CCLP + LENCCL), LENCCL, DUPFWD, DUPLIST,
NUMECS);
if (CCLNG(TCH) /= 0) then
J := 0;
for K in 0 .. LENCCL - 1 loop
ICH := CHARACTER'POS(CCLTBL(CCLP + K));
J := J + 1;
while (J < ICH) loop
SYMLIST(J) := TRUE;
J := J + 1;
end loop;
end loop;
J := J + 1;
while (J <= NUMECS) loop
SYMLIST(J) := TRUE;
J := J + 1;
end loop;
else
for K in 0 .. LENCCL - 1 loop
ICH := CHARACTER'POS(CCLTBL(CCLP + K));
SYMLIST(ICH) := TRUE;
end loop;
end if;
end if;
end if;
end loop;
end SYMPARTITION;
end DFA;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE DFA construction routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION converts non-deterministic finite automatons to finite ones.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/dfaS.a,v 1.4 90/01/12 15:19:52 self Exp Locker: self $
with MISC_DEFS;
with TEXT_IO;
package DFA is
use MISC_DEFS, TEXT_IO;
procedure CHECK_FOR_BACKTRACKING(DS : in INTEGER;
STATE : in UNBOUNDED_INT_ARRAY);
procedure CHECK_TRAILING_CONTEXT(NFA_STATES : in INT_PTR;
NUM_STATES : in INTEGER;
ACCSET : in INT_PTR;
NACC : in INTEGER);
procedure DUMP_ASSOCIATED_RULES(F : in FILE_TYPE;
DS : in INTEGER);
procedure DUMP_TRANSITIONS(F : in FILE_TYPE;
STATE : in UNBOUNDED_INT_ARRAY);
procedure EPSCLOSURE(T : in out INT_PTR;
NS_ADDR : in out INTEGER;
ACCSET : in out INT_PTR;
NACC_ADDR, HV_ADDR : out INTEGER;
RESULT : out INT_PTR);
procedure INCREASE_MAX_DFAS;
procedure NTOD;
procedure SNSTODS(SNS : in INT_PTR;
NUMSTATES : in INTEGER;
ACCSET : in INT_PTR;
NACC, HASHVAL : in INTEGER;
NEWDS_ADDR : out INTEGER;
RESULT : out BOOLEAN);
function SYMFOLLOWSET(DS : in INT_PTR;
DSIZE, TRANSSYM : in INTEGER;
NSET : in INT_PTR) return INTEGER;
procedure SYMPARTITION(DS : in INT_PTR;
NUMSTATES : in INTEGER;
SYMLIST : in out C_SIZE_BOOL_ARRAY;
DUPLIST : in out C_SIZE_ARRAY);
end DFA;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE equivalence class
-- AUTHOR: John Self (UCI)
-- DESCRIPTION finds equivalence classes so DFA will be smaller
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/ecsB.a,v 1.7 90/01/12 15:19:54 self Exp Locker: self $
with MISC_DEFS;
with MISC; use MISC_DEFS;
package body ECS is
-- ccl2ecl - convert character classes to set of equivalence classes
procedure CCL2ECL is
use MISC_DEFS;
ICH, NEWLEN, CCLP, CCLMEC : INTEGER;
begin
for I in 1 .. LASTCCL loop
-- we loop through each character class, and for each character
-- in the class, add the character's equivalence class to the
-- new "character" class we are creating. Thus when we are all
-- done, character classes will really consist of collections
-- of equivalence classes
NEWLEN := 0;
CCLP := CCLMAP(I);
for CCLS in 0 .. CCLLEN(I) - 1 loop
ICH := CHARACTER'POS(CCLTBL(CCLP + CCLS));
CCLMEC := ECGROUP(ICH);
if (CCLMEC > 0) then
CCLTBL(CCLP + NEWLEN) := CHARACTER'VAL(CCLMEC);
NEWLEN := NEWLEN + 1;
end if;
end loop;
CCLLEN(I) := NEWLEN;
end loop;
end CCL2ECL;
-- cre8ecs - associate equivalence class numbers with class members
-- fwd is the forward linked-list of equivalence class members. bck
-- is the backward linked-list, and num is the number of class members.
-- Returned is the number of classes.
procedure CRE8ECS(FWD, BCK : in out C_SIZE_ARRAY;
NUM : in INTEGER;
RESULT : out INTEGER) is
J, NUMCL : INTEGER;
begin
NUMCL := 0;
-- create equivalence class numbers. From now on, abs( bck(x) )
-- is the equivalence class number for object x. If bck(x)
-- is positive, then x is the representative of its equivalence
-- class.
for I in 1 .. NUM loop
if (BCK(I) = NIL) then
NUMCL := NUMCL + 1;
BCK(I) := NUMCL;
J := FWD(I);
while (J /= NIL) loop
BCK(J) := -NUMCL;
J := FWD(J);
end loop;
end if;
end loop;
RESULT := NUMCL;
return;
end CRE8ECS;
-- mkeccl - update equivalence classes based on character class xtions
-- where ccls contains the elements of the character class, lenccl is the
-- number of elements in the ccl, fwd is the forward link-list of equivalent
-- characters, bck is the backward link-list, and llsiz size of the link-list
procedure MKECCL(CCLS : in out CHAR_ARRAY;
LENCCL : in INTEGER;
FWD, BCK : in out UNBOUNDED_INT_ARRAY;
LLSIZ : in INTEGER) is
use MISC_DEFS, MISC;
CCLP, OLDEC, NEWEC, CCLM, I, J : INTEGER;
PROC_ARRAY : BOOLEAN_PTR;
begin
-- note that it doesn't matter whether or not the character class is
-- negated. The same results will be obtained in either case.
CCLP := CCLS'FIRST;
-- this array tells whether or not a character class has been processed.
PROC_ARRAY := new BOOLEAN_ARRAY(CCLS'FIRST .. CCLS'LAST);
for CCL_INDEX in CCLS'FIRST .. CCLS'LAST loop
PROC_ARRAY(CCL_INDEX) := FALSE;
end loop;
while (CCLP < LENCCL + CCLS'FIRST) loop
CCLM := CHARACTER'POS(CCLS(CCLP));
OLDEC := BCK(CCLM);
NEWEC := CCLM;
J := CCLP + 1;
I := FWD(CCLM);
while ((I /= NIL) and (I <= LLSIZ)) loop
-- look for the symbol in the character class
while ((J < LENCCL + CCLS'FIRST) and ((CCLS(J) <= CHARACTER'VAL(I)) or
PROC_ARRAY(J))) loop
if (CCLS(J) = CHARACTER'VAL(I)) then
-- we found an old companion of cclm in the ccl.
-- link it into the new equivalence class and flag it as
-- having been processed
BCK(I) := NEWEC;
FWD(NEWEC) := I;
NEWEC := I;
PROC_ARRAY(J) := TRUE;
-- set flag so we don't reprocess
-- get next equivalence class member
-- continue 2
goto NEXT_PT;
end if;
J := J + 1;
end loop;
-- symbol isn't in character class. Put it in the old equivalence
-- class
BCK(I) := OLDEC;
if (OLDEC /= NIL) then
FWD(OLDEC) := I;
end if;
OLDEC := I;
<<NEXT_PT>> I := FWD(I);
end loop;
if ((BCK(CCLM) /= NIL) or (OLDEC /= BCK(CCLM))) then
BCK(CCLM) := NIL;
FWD(OLDEC) := NIL;
end if;
FWD(NEWEC) := NIL;
-- find next ccl member to process
CCLP := CCLP + 1;
while ((CCLP < LENCCL + CCLS'FIRST) and PROC_ARRAY(CCLP)) loop
-- reset "doesn't need processing" flag
PROC_ARRAY(CCLP) := FALSE;
CCLP := CCLP + 1;
end loop;
end loop;
exception
when STORAGE_ERROR =>
MISC.AFLEXFATAL("dynamic memory failure in mkeccl()");
end MKECCL;
-- mkechar - create equivalence class for single character
procedure MKECHAR(TCH : in INTEGER;
FWD, BCK : in out C_SIZE_ARRAY) is
begin
-- if until now the character has been a proper subset of
-- an equivalence class, break it away to create a new ec
if (FWD(TCH) /= NIL) then
BCK(FWD(TCH)) := BCK(TCH);
end if;
if (BCK(TCH) /= NIL) then
FWD(BCK(TCH)) := FWD(TCH);
end if;
FWD(TCH) := NIL;
BCK(TCH) := NIL;
end MKECHAR;
end ECS;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE equivalence class
-- AUTHOR: John Self (UCI)
-- DESCRIPTION finds equivalence classes so DFA will be smaller
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/ecsS.a,v 1.4 90/01/12 15:19:57 self Exp Locker: self $
with MISC_DEFS; use MISC_DEFS;
package ECS is
procedure CCL2ECL;
procedure CRE8ECS(FWD, BCK : in out C_SIZE_ARRAY;
NUM : in INTEGER;
RESULT : out INTEGER);
procedure MKECCL(CCLS : in out CHAR_ARRAY;
LENCCL : in INTEGER;
FWD, BCK : in out UNBOUNDED_INT_ARRAY;
LLSIZ : in INTEGER);
procedure MKECHAR(TCH : in INTEGER;
FWD, BCK : in out C_SIZE_ARRAY);
end ECS;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE external_file_manager
-- AUTHOR: John Self (UCI)
-- DESCRIPTION opens external files for other functions
-- NOTES This package opens external files, and thus may be system dependent
-- because of limitations on file names.
-- This version is for the VADS 5.5 Ada development system.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/file_managerB.a,v 1.5 90/01/12 15:19:58 self Exp Locker: self $
with MISC_DEFS, TSTRING, TEXT_IO, MISC; use MISC_DEFS, TSTRING, TEXT_IO, MISC;
package body EXTERNAL_FILE_MANAGER is
-- FIX comment about compiler dependent
subtype SUFFIX_TYPE is STRING(1 .. 1);
function ADA_SUFFIX return SUFFIX_TYPE is
begin
return "a";
end ADA_SUFFIX;
procedure GET_IO_FILE(F : in out FILE_TYPE) is
begin
if (LEN(INFILENAME) /= 0) then
CREATE(F, OUT_FILE, STR(MISC.BASENAME) & "_io." & ADA_SUFFIX);
else
CREATE(F, OUT_FILE, "aflex_yy_io." & ADA_SUFFIX);
end if;
exception
when USE_ERROR | NAME_ERROR =>
MISC.AFLEXFATAL("could not create IO package file");
end GET_IO_FILE;
procedure GET_DFA_FILE(F : in out FILE_TYPE) is
begin
if (LEN(INFILENAME) /= 0) then
CREATE(F, OUT_FILE, STR(MISC.BASENAME) & "_dfa." & ADA_SUFFIX);
else
CREATE(F, OUT_FILE, "aflex_yy_dfa." & ADA_SUFFIX);
end if;
exception
when USE_ERROR | NAME_ERROR =>
MISC.AFLEXFATAL("could not create DFA package file");
end GET_DFA_FILE;
procedure GET_SCANNER_FILE(F : in out FILE_TYPE) is
OUTFILE_NAME : VSTRING;
begin
if (LEN(INFILENAME) /= 0) then
-- give out infile + ada_suffix
OUTFILE_NAME := MISC.BASENAME & "." & ADA_SUFFIX;
else
OUTFILE_NAME := VSTR("aflex_yy." & ADA_SUFFIX);
end if;
CREATE(F, OUT_FILE, STR(OUTFILE_NAME));
SET_OUTPUT(F);
exception
when NAME_ERROR | USE_ERROR =>
MISC.AFLEXFATAL("can't create scanner file " & OUTFILE_NAME);
end GET_SCANNER_FILE;
procedure GET_BACKTRACK_FILE(F : in out FILE_TYPE) is
begin
CREATE(F, OUT_FILE, "aflex.backtrack");
exception
when USE_ERROR | NAME_ERROR =>
MISC.AFLEXFATAL("could not create backtrack file");
end GET_BACKTRACK_FILE;
procedure INITIALIZE_FILES is
begin
null;
-- doesn't need to do anything on Verdix
end INITIALIZE_FILES;
end EXTERNAL_FILE_MANAGER;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE external_file_manager
-- AUTHOR: John Self (UCI)
-- DESCRIPTION opens external files for other functions
-- NOTES This package opens external files, and thus may be system dependent
-- because of limitations on file names.
-- This version is for the VADS 5.5 Ada development system.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/file_managerS.a,v 1.4 90/01/12 15:20:00 self Exp Locker: self $
with TEXT_IO; use TEXT_IO;
package EXTERNAL_FILE_MANAGER is
procedure GET_IO_FILE(F : in out FILE_TYPE);
procedure GET_DFA_FILE(F : in out FILE_TYPE);
procedure GET_SCANNER_FILE(F : in out FILE_TYPE);
procedure GET_BACKTRACK_FILE(F : in out FILE_TYPE);
procedure INITIALIZE_FILES;
end EXTERNAL_FILE_MANAGER;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE file strings
-- AUTHOR: John Self (UCI)
-- DESCRIPTION used to store lines in the template files
-- NOTES if lines in a template exceed 128 characters we are in trouble
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/file_strings.a,v 1.3 90/01/12 15:20:02 self Exp Locker: self $
with VSTRINGS;
package FILE_STRING is
new VSTRINGS(128);
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE scanner generation
-- AUTHOR: John Self (UCI)
-- DESCRIPTION
-- NOTES does actual generation (writing) of output aflex scanners
-- $Header: /dc/uc/self/arcadia/aflex/ada/src/RCS/genB.a,v 1.25 1992/10/02 23:08:41 self Exp self $
with MISC_DEFS, TEXT_IO, MISC, INT_IO, TSTRING, PARSE_TOKENS;
with SCANNER, SKELETON_MANAGER, EXTERNAL_FILE_MANAGER; use MISC_DEFS, TEXT_IO,
TSTRING, PARSE_TOKENS, EXTERNAL_FILE_MANAGER;
package body GEN is
INDENT_LEVEL : INTEGER := 0; -- each level is 4 spaces
MAX_SHORT : constant INTEGER := 32767;
procedure INDENT_UP is
begin
INDENT_LEVEL := INDENT_LEVEL + 1;
end INDENT_UP;
pragma INLINE(INDENT_UP);
procedure INDENT_DOWN is
begin
INDENT_LEVEL := INDENT_LEVEL - 1;
end INDENT_DOWN;
pragma INLINE(INDENT_DOWN);
procedure SET_INDENT(INDENT_VAL : in INTEGER) is
begin
INDENT_LEVEL := INDENT_VAL;
end SET_INDENT;
-- indent to the current level
procedure DO_INDENT is
I : INTEGER := INDENT_LEVEL*4;
begin
while (I >= 8) loop
TEXT_IO.PUT(ASCII.HT);
I := I - 8;
end loop;
while (I > 0) loop
TEXT_IO.PUT(' ');
I := I - 1;
end loop;
end DO_INDENT;
-- generate the code to keep backtracking information
procedure GEN_BACKTRACKING is
begin
if (NUM_BACKTRACKING = 0) then
return;
end if;
INDENT_PUTS("if ( yy_accept(yy_current_state) /= 0 ) then");
INDENT_UP;
INDENT_PUTS("yy_last_accepting_state := yy_current_state;");
INDENT_PUTS("yy_last_accepting_cpos := yy_cp;");
INDENT_DOWN;
INDENT_PUTS("end if;");
end GEN_BACKTRACKING;
-- generate the code to perform the backtrack
procedure GEN_BT_ACTION is
begin
if (NUM_BACKTRACKING = 0) then
return;
end if;
SET_INDENT(4);
INDENT_PUTS("when 0 => -- must backtrack");
INDENT_PUTS("-- undo the effects of YY_DO_BEFORE_ACTION");
INDENT_PUTS("yy_ch_buf(yy_cp) := yy_hold_char;");
if (FULLTBL) then
INDENT_PUTS("yy_cp := yy_last_accepting_cpos + 1;");
else
-- backtracking info for compressed tables is taken \after/
-- yy_cp has been incremented for the next state
INDENT_PUTS("yy_cp := yy_last_accepting_cpos;");
end if;
INDENT_PUTS("yy_current_state := yy_last_accepting_state;");
INDENT_PUTS("goto next_action;");
TEXT_IO.NEW_LINE;
SET_INDENT(0);
end GEN_BT_ACTION;
-- generate equivalence-class table
procedure GENECS is
I : INTEGER;
NUMROWS : INTEGER;
use TEXT_IO;
begin
TEXT_IO.PUT("yy_ec : constant array(CHARACTER'FIRST..");
TEXT_IO.PUT_LINE("CHARACTER'LAST) of short :=");
TEXT_IO.PUT_LINE(" ( 0,");
for CHAR_COUNT in 1 .. CSIZE loop
if (CASEINS and ((CHAR_COUNT >= CHARACTER'POS('A')) and (CHAR_COUNT <=
CHARACTER'POS('Z')))) then
ECGROUP(CHAR_COUNT) := ECGROUP(MISC.CLOWER(CHAR_COUNT));
end if;
ECGROUP(CHAR_COUNT) := abs(ECGROUP(CHAR_COUNT));
MISC.MKDATA(ECGROUP(CHAR_COUNT));
end loop;
MISC.DATAEND;
if (TRACE) then
TEXT_IO.NEW_LINE(STANDARD_ERROR);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
TEXT_IO.PUT(STANDARD_ERROR, "Equivalence Classes:");
TEXT_IO.NEW_LINE(STANDARD_ERROR);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
NUMROWS := (CSIZE + 1)/8;
for J in 1 .. NUMROWS loop
I := J;
while (I <= CSIZE) loop
TSTRING.PUT(STANDARD_ERROR, MISC.READABLE_FORM(CHARACTER'VAL(I)));
TEXT_IO.PUT(STANDARD_ERROR, " = ");
INT_IO.PUT(STANDARD_ERROR, ECGROUP(I), 1);
TEXT_IO.PUT(STANDARD_ERROR, " ");
I := I + NUMROWS;
end loop;
TEXT_IO.NEW_LINE(STANDARD_ERROR);
end loop;
end if;
end GENECS;
-- generate the code to find the action number
procedure GEN_FIND_ACTION is
begin
INDENT_PUTS("yy_act := yy_accept(yy_current_state);");
end GEN_FIND_ACTION;
-- genftbl - generates full transition table
procedure GENFTBL is
END_OF_BUFFER_ACTION : INTEGER := NUM_RULES + 1;
-- *everything* is done in terms of arrays starting at 1, so provide
-- a null entry for the zero element of all C arrays
use TEXT_IO;
begin
TEXT_IO.PUT("yy_accept : constant array(0..");
INT_IO.PUT(LASTDFA, 1);
TEXT_IO.PUT_LINE(") of short :=");
TEXT_IO.PUT_LINE(" ( 0,");
DFAACC(END_OF_BUFFER_STATE).DFAACC_STATE := END_OF_BUFFER_ACTION;
for I in 1 .. LASTDFA loop
declare
ANUM : INTEGER := DFAACC(I).DFAACC_STATE;
begin
MISC.MKDATA(ANUM);
if (TRACE and (ANUM /= 0)) then
TEXT_IO.PUT(STANDARD_ERROR, "state # ");
INT_IO.PUT(STANDARD_ERROR, I, 1);
TEXT_IO.PUT(STANDARD_ERROR, " accepts: [");
INT_IO.PUT(STANDARD_ERROR, ANUM, 1);
TEXT_IO.PUT(STANDARD_ERROR, "]");
TEXT_IO.NEW_LINE(STANDARD_ERROR);
end if;
end;
end loop;
MISC.DATAEND;
if (USEECS) then
GENECS;
end if;
-- don't have to dump the actual full table entries - they were created
-- on-the-fly
end GENFTBL;
-- generate the code to find the next compressed-table state
procedure GEN_NEXT_COMPRESSED_STATE is
begin
if (USEECS) then
INDENT_PUTS("yy_c := yy_ec(yy_ch_buf(yy_cp));");
else
INDENT_PUTS("yy_c := yy_ch_buf(yy_cp);");
end if;
-- save the backtracking info \before/ computing the next state
-- because we always compute one more state than needed - we
-- always proceed until we reach a jam state
GEN_BACKTRACKING;
INDENT_PUTS(
"while ( yy_chk(yy_base(yy_current_state) + yy_c) /= yy_current_state ) loop"
);
INDENT_UP;
INDENT_PUTS("yy_current_state := yy_def(yy_current_state);");
if (USEMECS) then
-- we've arrange it so that templates are never chained
-- to one another. This means we can afford make a
-- very simple test to see if we need to convert to
-- yy_c's meta-equivalence class without worrying
-- about erroneously looking up the meta-equivalence
-- class twice
DO_INDENT;
-- lastdfa + 2 is the beginning of the templates
TEXT_IO.PUT("if ( yy_current_state >= ");
INT_IO.PUT(LASTDFA + 2, 1);
TEXT_IO.PUT_LINE(" ) then");
INDENT_UP;
INDENT_PUTS("yy_c := yy_meta(yy_c);");
INDENT_DOWN;
INDENT_PUTS("end if;");
end if;
INDENT_DOWN;
INDENT_PUTS("end loop;");
INDENT_PUTS("yy_current_state := yy_nxt(yy_base(yy_current_state) + yy_c);")
;
INDENT_DOWN;
end GEN_NEXT_COMPRESSED_STATE;
-- generate the code to find the next match
procedure GEN_NEXT_MATCH is
-- note - changes in here should be reflected in get_next_state
begin
if (FULLTBL) then
INDENT_PUTS(
"yy_current_state := yy_nxt(yy_current_state, yy_ch_buf(yy_cp));");
INDENT_PUTS("while ( yy_current_state > 0 ) loop");
INDENT_UP;
INDENT_PUTS("yy_cp := yy_cp + 1;");
INDENT_PUTS(
"yy_current_state := yy_nxt(yy_current_state, yy_ch_buf(yy_cp));");
INDENT_DOWN;
INDENT_PUTS("end loop;");
if (NUM_BACKTRACKING > 0) then
GEN_BACKTRACKING;
TEXT_IO.NEW_LINE;
end if;
TEXT_IO.NEW_LINE;
INDENT_PUTS("yy_current_state := -yy_current_state;");
else
-- compressed
INDENT_PUTS("loop");
INDENT_UP;
GEN_NEXT_STATE;
INDENT_PUTS("yy_cp := yy_cp + 1;");
if (INTERACTIVE) then
TEXT_IO.PUT("if ( yy_base(yy_current_state) = ");
INT_IO.PUT(JAMBASE, 1);
else
TEXT_IO.PUT("if ( yy_current_state = ");
INT_IO.PUT(JAMSTATE, 1);
end if;
TEXT_IO.PUT_LINE(" ) then");
TEXT_IO.PUT_LINE(" exit;");
TEXT_IO.PUT_LINE("end if;");
INDENT_DOWN;
DO_INDENT;
TEXT_IO.PUT_LINE("end loop;");
if (not INTERACTIVE) then
INDENT_PUTS("yy_cp := yy_last_accepting_cpos;");
INDENT_PUTS("yy_current_state := yy_last_accepting_state;");
end if;
end if;
end GEN_NEXT_MATCH;
-- generate the code to find the next state
procedure GEN_NEXT_STATE is
-- note - changes in here should be reflected in get_next_match
begin
INDENT_UP;
if (FULLTBL) then
INDENT_PUTS("yy_current_state := yy_nxt(yy_current_state,");
INDENT_PUTS(" yy_ch_buf(yy_cp));");
GEN_BACKTRACKING;
else
GEN_NEXT_COMPRESSED_STATE;
end if;
end GEN_NEXT_STATE;
-- generate the code to find the start state
procedure GEN_START_STATE is
begin
INDENT_PUTS("yy_current_state := yy_start;");
if (BOL_NEEDED) then
INDENT_PUTS("if ( yy_ch_buf(yy_bp-1) = ASCII.LF ) then");
INDENT_UP;
INDENT_PUTS("yy_current_state := yy_current_state + 1;");
INDENT_DOWN;
INDENT_PUTS("end if;");
end if;
end GEN_START_STATE;
-- gentabs - generate data statements for the transition tables
procedure GENTABS is
I, J, K, NACC, TOTAL_STATES : INTEGER;
ACCSET, ACC_ARRAY : INT_PTR;
ACCNUM : INTEGER;
END_OF_BUFFER_ACTION : INTEGER := NUM_RULES + 1;
-- *everything* is done in terms of arrays starting at 1, so provide
-- a null entry for the zero element of all C arrays
C_LONG_DECL : STRING(1 .. 44) :=
"static const long int %s[%d] =\n { 0,\n";
C_SHORT_DECL : STRING(1 .. 45) :=
"static const short int %s[%d] =\n { 0,\n";
C_CHAR_DECL : STRING(1 .. 40) :=
"static const char %s[%d] =\n { 0,\n";
begin
ACC_ARRAY := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_DFAS);
NUMMT := 0;
-- the compressed table format jams by entering the "jam state",
-- losing information about the previous state in the process.
-- In order to recover the previous state, we effectively need
-- to keep backtracking information.
NUM_BACKTRACKING := NUM_BACKTRACKING + 1;
DFAACC(END_OF_BUFFER_STATE).DFAACC_STATE := END_OF_BUFFER_ACTION;
for CNT in 1 .. LASTDFA loop
ACC_ARRAY(CNT) := DFAACC(CNT).DFAACC_STATE;
end loop;
ACC_ARRAY(LASTDFA + 1) := 0;
-- add accepting number for the jam state
-- spit out ALIST array, dumping the accepting numbers.
-- "lastdfa + 2" is the size of ALIST; includes room for arrays
-- beginning at 0 and for "jam" state
K := LASTDFA + 2;
TEXT_IO.PUT("yy_accept : constant array(0..");
INT_IO.PUT(K - 1, 1);
TEXT_IO.PUT_LINE(") of short :=");
TEXT_IO.PUT_LINE(" ( 0,");
for CNT in 1 .. LASTDFA loop
MISC.MKDATA(ACC_ARRAY(CNT));
if (TRACE and (ACC_ARRAY(CNT) /= 0)) then
TEXT_IO.PUT(STANDARD_ERROR, "state # ");
INT_IO.PUT(STANDARD_ERROR, CNT, 1);
TEXT_IO.PUT(STANDARD_ERROR, " accepts: [");
INT_IO.PUT(STANDARD_ERROR, ACC_ARRAY(CNT), 1);
TEXT_IO.PUT(STANDARD_ERROR, ']');
TEXT_IO.NEW_LINE(STANDARD_ERROR);
end if;
end loop;
-- add entry for "jam" state
MISC.MKDATA(ACC_ARRAY(LASTDFA + 1));
MISC.DATAEND;
if (USEECS) then
GENECS;
end if;
if (USEMECS) then
-- write out meta-equivalence classes (used to index templates with)
if (TRACE) then
TEXT_IO.NEW_LINE(STANDARD_ERROR);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
TEXT_IO.PUT_LINE(STANDARD_ERROR, "Meta-Equivalence Classes:");
end if;
TEXT_IO.PUT("yy_meta : constant array(0..");
INT_IO.PUT(NUMECS, 1);
TEXT_IO.PUT_LINE(") of short :=");
TEXT_IO.PUT_LINE(" ( 0,");
for CNT in 1 .. NUMECS loop
if (TRACE) then
INT_IO.PUT(STANDARD_ERROR, CNT, 1);
TEXT_IO.PUT(STANDARD_ERROR, " = ");
INT_IO.PUT(STANDARD_ERROR, abs(TECBCK(CNT)), 1);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
end if;
MISC.MKDATA(abs(TECBCK(CNT)));
end loop;
MISC.DATAEND;
end if;
TOTAL_STATES := LASTDFA + NUMTEMPS;
TEXT_IO.PUT("yy_base : constant array(0..");
INT_IO.PUT(TOTAL_STATES, 1);
if (TBLEND > MAX_SHORT) then
TEXT_IO.PUT_LINE(") of integer :=");
else
TEXT_IO.PUT_LINE(") of short :=");
end if;
TEXT_IO.PUT_LINE(" ( 0,");
for CNT in 1 .. LASTDFA loop
declare
D : INTEGER := DEF(CNT);
begin
if (BASE(CNT) = JAMSTATE_CONST) then
BASE(CNT) := JAMBASE;
end if;
if (D = JAMSTATE_CONST) then
DEF(CNT) := JAMSTATE;
else
if (D < 0) then
-- template reference
TMPUSES := TMPUSES + 1;
DEF(CNT) := LASTDFA - D + 1;
end if;
end if;
MISC.MKDATA(BASE(CNT));
end;
end loop;
-- generate jam state's base index
I := LASTDFA + 1;
MISC.MKDATA(BASE(I));
-- skip jam state
I := I + 1;
for CNT in I .. TOTAL_STATES loop
MISC.MKDATA(BASE(CNT));
DEF(CNT) := JAMSTATE;
end loop;
MISC.DATAEND;
TEXT_IO.PUT("yy_def : constant array(0..");
INT_IO.PUT(TOTAL_STATES, 1);
if (TBLEND > MAX_SHORT) then
TEXT_IO.PUT_LINE(") of integer :=");
else
TEXT_IO.PUT_LINE(") of short :=");
end if;
TEXT_IO.PUT_LINE(" ( 0,");
for CNT in 1 .. TOTAL_STATES loop
MISC.MKDATA(DEF(CNT));
end loop;
MISC.DATAEND;
TEXT_IO.PUT("yy_nxt : constant array(0..");
INT_IO.PUT(TBLEND, 1);
if (LASTDFA > MAX_SHORT) then
TEXT_IO.PUT_LINE(") of integer :=");
else
TEXT_IO.PUT_LINE(") of short :=");
end if;
TEXT_IO.PUT_LINE(" ( 0,");
for CNT in 1 .. TBLEND loop
if ((NXT(CNT) = 0) or (CHK(CNT) = 0)) then
NXT(CNT) := JAMSTATE;
-- new state is the JAM state
end if;
MISC.MKDATA(NXT(CNT));
end loop;
MISC.DATAEND;
TEXT_IO.PUT("yy_chk : constant array(0..");
INT_IO.PUT(TBLEND, 1);
if (LASTDFA > MAX_SHORT) then
TEXT_IO.PUT_LINE(") of integer :=");
else
TEXT_IO.PUT_LINE(") of short :=");
end if;
TEXT_IO.PUT_LINE(" ( 0,");
for CNT in 1 .. TBLEND loop
if (CHK(CNT) = 0) then
NUMMT := NUMMT + 1;
end if;
MISC.MKDATA(CHK(CNT));
end loop;
MISC.DATAEND;
exception
when STORAGE_ERROR =>
MISC.AFLEXFATAL("dynamic memory failure in gentabs()");
end GENTABS;
-- write out a string at the current indentation level, adding a final
-- newline
procedure INDENT_PUTS(STR : in STRING) is
begin
DO_INDENT;
TEXT_IO.PUT_LINE(STR);
end INDENT_PUTS;
-- do_sect3_out - dumps section 3.
procedure DO_SECT3_OUT is
GARBAGE : TOKEN;
begin
SCANNER.CALL_YYLEX := TRUE;
GARBAGE := SCANNER.GET_TOKEN;
end DO_SECT3_OUT;
-- make_tables - generate transition tables
--
--
-- Generates transition tables and finishes generating output file
procedure MAKE_TABLES is
DID_EOF_RULE : BOOLEAN := FALSE;
TRANS_OFFSET_TYPE : STRING(1 .. 7);
TOTAL_TABLE_SIZE : INTEGER := TBLEND + NUMECS + 1;
BUF : VSTRING;
begin
if (not FULLTBL) then
-- if we used full tables this is already output
DO_SECT3_OUT;
-- intent of this call is to get everything up to ##
SKELETON_MANAGER.SKELOUT;
-- output YYLex code up to part about tables.
end if;
TEXT_IO.PUT("YY_END_OF_BUFFER : constant := ");
INT_IO.PUT(NUM_RULES + 1, 1);
TEXT_IO.PUT_LINE(";");
INDENT_PUTS("subtype yy_state_type is integer;");
INDENT_PUTS("yy_current_state : yy_state_type;");
-- now output the constants for the various start conditions
RESET(DEF_FILE, IN_FILE);
while (not TEXT_IO.END_OF_FILE(DEF_FILE)) loop
TSTRING.GET_LINE(DEF_FILE, BUF);
TSTRING.PUT_LINE(BUF);
end loop;
if (FULLTBL) then
GENFTBL;
else
GENTABS;
end if;
RESET(TEMP_ACTION_FILE, IN_FILE);
-- generate code for yy_get_previous_state
SET_INDENT(1);
SKELETON_MANAGER.SKELOUT;
if (BOL_NEEDED) then
INDENT_PUTS("yy_bp : integer := yytext_ptr;");
end if;
SKELETON_MANAGER.SKELOUT;
GEN_START_STATE;
SKELETON_MANAGER.SKELOUT;
GEN_NEXT_STATE;
SKELETON_MANAGER.SKELOUT;
SET_INDENT(2);
INDENT_PUTS("yy_bp := yy_cp;");
GEN_START_STATE;
GEN_NEXT_MATCH;
SKELETON_MANAGER.SKELOUT;
SET_INDENT(3);
GEN_FIND_ACTION;
SET_INDENT(1);
SKELETON_MANAGER.SKELOUT;
INDENT_UP;
GEN_BT_ACTION;
MISC.ACTION_OUT;
MISC.ACTION_OUT;
-- generate cases for any missing EOF rules
for I in 1 .. LASTSC loop
if (not SCEOF(I)) then
DO_INDENT;
if (not DID_EOF_RULE) then
TEXT_IO.PUT("when ");
else
TEXT_IO.PUT_LINE("|");
end if;
TEXT_IO.PUT("YY_END_OF_BUFFER + ");
TSTRING.PUT(SCNAME(I));
TEXT_IO.PUT(" + 1 ");
DID_EOF_RULE := TRUE;
end if;
end loop;
if (DID_EOF_RULE) then
TEXT_IO.PUT_LINE("=> ");
end if;
if (DID_EOF_RULE) then
INDENT_UP;
INDENT_PUTS("return End_Of_Input;");
INDENT_DOWN;
end if;
SKELETON_MANAGER.SKELOUT;
-- copy remainder of input to output
MISC.LINE_DIRECTIVE_OUT;
DO_SECT3_OUT;
-- copy remainder of input, after ##, to the scanner file.
end MAKE_TABLES;
end GEN;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE scanner generation
-- AUTHOR: John Self (UCI)
-- DESCRIPTION
-- NOTES does actual generation (writing) of output aflex scanners
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/genS.a,v 1.4 90/01/12 15:20:07 self Exp Locker: self $
with MISC_DEFS; use MISC_DEFS;
package GEN is
procedure DO_INDENT;
procedure GEN_BACKTRACKING;
procedure GEN_BT_ACTION;
procedure GEN_FIND_ACTION;
procedure GEN_NEXT_COMPRESSED_STATE;
procedure GEN_NEXT_MATCH;
procedure GEN_NEXT_STATE;
procedure GEN_START_STATE;
procedure GENECS;
procedure GENFTBL;
procedure INDENT_PUTS(STR : in STRING);
procedure GENTABS;
procedure INDENT_DOWN;
procedure INDENT_UP;
procedure SET_INDENT(INDENT_VAL : in INTEGER);
procedure MAKE_TABLES;
procedure DO_SECT3_OUT;
end GEN;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE integer IO
-- AUTHOR: John Self (UCI)
-- DESCRIPTION instantiation of integer IO generic for integers
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/int_io.a,v 1.3 90/01/12 15:20:09 self Exp Locker: self $
with TEXT_IO;
package INT_IO is
new TEXT_IO.INTEGER_IO(INTEGER);
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE main body
-- AUTHOR: John Self (UCI)
-- DESCRIPTION driver routines for aflex. Calls drivers for all
-- high level routines from other packages.
-- $Header: /dc/uc/self/arcadia/aflex/ada/src/RCS/mainB.a,v 1.24 1991/07/22 18:06:53 self Exp self $
with MISC_DEFS, MISC, COMMAND_LINE_INTERFACE, DFA, ECS, GEN, TEXT_IO, PARSER;
with MAIN_BODY, TSTRING, PARSE_TOKENS, SKELETON_MANAGER, EXTERNAL_FILE_MANAGER;
with EXTERNAL_FILE_MANAGER, INT_IO; use MISC_DEFS, COMMAND_LINE_INTERFACE,
TSTRING, EXTERNAL_FILE_MANAGER;
package body MAIN_BODY is
OUTFILE_CREATED : BOOLEAN := FALSE;
AFLEX_VERSION : CONSTANT STRING := "1.1d";
STARTTIME, ENDTIME : VSTRING;
-- aflexend - terminate aflex
--
-- note
-- This routine does not return.
procedure AFLEXEND(STATUS : in INTEGER) is
use TEXT_IO;
TBLSIZ : INTEGER;
begin
TERMINATION_STATUS := STATUS;
-- we'll return this value of the OS.
if (IS_OPEN(SKELFILE)) then
CLOSE(SKELFILE);
end if;
if (IS_OPEN(TEMP_ACTION_FILE)) then
DELETE(TEMP_ACTION_FILE);
end if;
if (IS_OPEN(DEF_FILE)) then
DELETE(DEF_FILE);
end if;
if (BACKTRACK_REPORT) then
if (NUM_BACKTRACKING = 0) then
TEXT_IO.PUT_LINE(BACKTRACK_FILE, "No backtracking.");
else
if (FULLTBL) then
INT_IO.PUT(BACKTRACK_FILE, NUM_BACKTRACKING, 0);
TEXT_IO.PUT_LINE(BACKTRACK_FILE,
" backtracking (non-accepting) states.");
else
TEXT_IO.PUT_LINE(BACKTRACK_FILE, "Compressed tables always backtrack."
);
end if;
end if;
CLOSE(BACKTRACK_FILE);
end if;
if (PRINTSTATS) then
ENDTIME := MISC.AFLEX_GETTIME;
TEXT_IO.PUT_LINE(STANDARD_ERROR, "aflex version " & AFLEX_VERSION &
" usage statistics:");
TSTRING.PUT_LINE(STANDARD_ERROR, " started at " & STARTTIME &
", finished at " & ENDTIME);
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, LASTNFA, 0);
TEXT_IO.PUT(STANDARD_ERROR, '/');
INT_IO.PUT(STANDARD_ERROR, CURRENT_MNS, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " NFA states");
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, LASTDFA, 0);
TEXT_IO.PUT(STANDARD_ERROR, '/');
INT_IO.PUT(STANDARD_ERROR, CURRENT_MAX_DFAS, 0);
TEXT_IO.PUT(STANDARD_ERROR, " DFA states (");
INT_IO.PUT(STANDARD_ERROR, TOTNST, 0);
TEXT_IO.PUT(STANDARD_ERROR, " words)");
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUM_RULES - 1, 0);
-- - 1 for def. rule
TEXT_IO.PUT_LINE(STANDARD_ERROR, " rules");
if (NUM_BACKTRACKING = 0) then
TEXT_IO.PUT_LINE(STANDARD_ERROR, " No backtracking");
else
if (FULLTBL) then
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUM_BACKTRACKING, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR,
" backtracking (non-accepting) states");
else
TEXT_IO.PUT_LINE(STANDARD_ERROR, " compressed tables always backtrack"
);
end if;
end if;
if (BOL_NEEDED) then
TEXT_IO.PUT_LINE(STANDARD_ERROR, " Beginning-of-line patterns used");
end if;
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, LASTSC, 0);
TEXT_IO.PUT(STANDARD_ERROR, '/');
INT_IO.PUT(STANDARD_ERROR, CURRENT_MAX_SCS, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " start conditions");
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUMEPS, 0);
TEXT_IO.PUT(STANDARD_ERROR, " epsilon states, ");
INT_IO.PUT(STANDARD_ERROR, EPS2, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " double epsilon states");
if (LASTCCL = 0) then
TEXT_IO.PUT_LINE(STANDARD_ERROR, " no character classes");
else
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, LASTCCL, 0);
TEXT_IO.PUT(STANDARD_ERROR, '/');
INT_IO.PUT(STANDARD_ERROR, CURRENT_MAXCCLS, 0);
TEXT_IO.PUT(STANDARD_ERROR, " character classes needed ");
INT_IO.PUT(STANDARD_ERROR, CCLMAP(LASTCCL) + CCLLEN(LASTCCL), 0);
TEXT_IO.PUT(STANDARD_ERROR, '/');
INT_IO.PUT(STANDARD_ERROR, CURRENT_MAX_CCL_TBL_SIZE, 0);
TEXT_IO.PUT(STANDARD_ERROR, " words of storage, ");
INT_IO.PUT(STANDARD_ERROR, CCLREUSE, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, "reused");
end if;
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUMSNPAIRS, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " state/nextstate pairs created");
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUMUNIQ, 0);
TEXT_IO.PUT(STANDARD_ERROR, '/');
INT_IO.PUT(STANDARD_ERROR, NUMDUP, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " unique/duplicate transitions");
if (FULLTBL) then
TBLSIZ := LASTDFA*NUMECS;
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, TBLSIZ, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " table entries");
else
TBLSIZ := 2*(LASTDFA + NUMTEMPS) + 2*TBLEND;
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, LASTDFA + NUMTEMPS, 0);
TEXT_IO.PUT(STANDARD_ERROR, '/');
INT_IO.PUT(STANDARD_ERROR, CURRENT_MAX_DFAS, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " base-def entries created");
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, TBLEND, 0);
TEXT_IO.PUT(STANDARD_ERROR, '/');
INT_IO.PUT(STANDARD_ERROR, CURRENT_MAX_XPAIRS, 0);
TEXT_IO.PUT(STANDARD_ERROR, " (peak ");
INT_IO.PUT(STANDARD_ERROR, PEAKPAIRS, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, ") nxt-chk entries created");
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUMTEMPS*NUMMECS, 0);
TEXT_IO.PUT(STANDARD_ERROR, '/');
INT_IO.PUT(STANDARD_ERROR, CURRENT_MAX_TEMPLATE_XPAIRS, 0);
TEXT_IO.PUT(STANDARD_ERROR, " (peak ");
INT_IO.PUT(STANDARD_ERROR, NUMTEMPS*NUMECS, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, ") template nxt-chk entries created");
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUMMT, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " empty table entries");
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUMPROTS, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " protos created");
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUMTEMPS, 0);
TEXT_IO.PUT(STANDARD_ERROR, " templates created, ");
INT_IO.PUT(STANDARD_ERROR, TMPUSES, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, "uses");
end if;
if (USEECS) then
TBLSIZ := TBLSIZ + CSIZE;
TEXT_IO.PUT_LINE(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUMECS, 0);
TEXT_IO.PUT(STANDARD_ERROR, '/');
INT_IO.PUT(STANDARD_ERROR, CSIZE, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " equivalence classes created");
end if;
if (USEMECS) then
TBLSIZ := TBLSIZ + NUMECS;
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUMMECS, 0);
TEXT_IO.PUT(STANDARD_ERROR, '/');
INT_IO.PUT(STANDARD_ERROR, CSIZE, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " meta-equivalence classes created");
end if;
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, HSHCOL, 0);
TEXT_IO.PUT(STANDARD_ERROR, " (");
INT_IO.PUT(STANDARD_ERROR, HSHSAVE, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " saved) hash collisions, ");
INT_IO.PUT(STANDARD_ERROR, DFAEQL, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " DFAs equal");
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, NUM_REALLOCS, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " sets of reallocations needed");
TEXT_IO.PUT(STANDARD_ERROR, " ");
INT_IO.PUT(STANDARD_ERROR, TBLSIZ, 0);
TEXT_IO.PUT_LINE(STANDARD_ERROR, " total table entries needed");
end if;
if (STATUS /= 0) then
raise AFLEX_TERMINATE;
end if;
end AFLEXEND;
-- aflexinit - initialize aflex
procedure AFLEXINIT is
use TEXT_IO, TSTRING;
SAWCMPFLAG, USE_STDOUT : BOOLEAN;
OUTPUT_FILE : FILE_TYPE;
INPUT_FILE : FILE_TYPE;
I : INTEGER;
ARG_CNT : INTEGER;
FLAG_POS : INTEGER;
ARG : VSTRING;
SKELNAME : VSTRING;
SKELNAME_USED : BOOLEAN := FALSE;
begin
PRINTSTATS := FALSE;
SYNTAXERROR := FALSE;
TRACE := FALSE;
SPPRDFLT := FALSE;
INTERACTIVE := FALSE;
CASEINS := FALSE;
BACKTRACK_REPORT := FALSE;
PERFORMANCE_REPORT := FALSE;
DDEBUG := FALSE;
FULLTBL := FALSE;
CONTINUED_ACTION := FALSE;
GEN_LINE_DIRS := TRUE;
USEMECS := TRUE;
USEECS := TRUE;
SAWCMPFLAG := FALSE;
USE_STDOUT := FALSE;
-- read flags
COMMAND_LINE_INTERFACE.INITIALIZE_COMMAND_LINE;
-- load up argv
EXTERNAL_FILE_MANAGER.INITIALIZE_FILES;
-- do external files setup
-- loop through the list of arguments
ARG_CNT := 1;
while (ARG_CNT <= ARGC - 1) loop
if ((CHAR(ARGV(ARG_CNT), 1) /= '-') or (LEN(ARGV(ARG_CNT)) < 2)) then
exit;
end if;
-- loop through the flags in this argument.
ARG := ARGV(ARG_CNT);
FLAG_POS := 2;
while (FLAG_POS <= LEN(ARG)) loop
case CHAR(ARG, FLAG_POS) is
when 'b' =>
BACKTRACK_REPORT := TRUE;
when 'd' =>
DDEBUG := TRUE;
when 'f' =>
USEECS := FALSE;
USEMECS := FALSE;
FULLTBL := TRUE;
when 'I' =>
INTERACTIVE := TRUE;
when 'i' =>
CASEINS := TRUE;
when 'L' =>
GEN_LINE_DIRS := FALSE;
when 'p' =>
PERFORMANCE_REPORT := TRUE;
when 'S' =>
if (FLAG_POS /= 2) then
MISC.AFLEXERROR("-S flag must be given separately");
end if;
SKELNAME := SLICE(ARG, FLAG_POS + 1, LEN(ARG));
SKELNAME_USED := TRUE;
goto GET_NEXT_ARG;
when 's' =>
SPPRDFLT := TRUE;
when 't' =>
USE_STDOUT := TRUE;
when 'T' =>
TRACE := TRUE;
when 'v' =>
PRINTSTATS := TRUE;
when others =>
MISC.AFLEXERROR("unknown flag " & CHAR(ARG, FLAG_POS));
end case;
FLAG_POS := FLAG_POS + 1;
end loop;
<<GET_NEXT_ARG>> ARG_CNT := ARG_CNT + 1;
-- go on to next argument from list.
end loop;
if (FULLTBL and USEMECS) then
MISC.AFLEXERROR("full table and -cm don't make sense together");
end if;
if (FULLTBL and INTERACTIVE) then
MISC.AFLEXERROR("full table and -I are (currently) incompatible");
end if;
if (ARG_CNT < ARGC) then
begin
if (ARG_CNT - ARGC > 1) then
MISC.AFLEXERROR("extraneous argument(s) given");
end if;
-- Tell aflex where to read input from.
INFILENAME := ARGV(ARG_CNT);
OPEN(INPUT_FILE, IN_FILE, STR(ARGV(ARG_CNT)));
SET_INPUT(INPUT_FILE);
exception
when NAME_ERROR =>
MISC.AFLEXFATAL("can't open " & INFILENAME);
end;
end if;
if (not USE_STDOUT) then
EXTERNAL_FILE_MANAGER.GET_SCANNER_FILE(OUTPUT_FILE);
OUTFILE_CREATED := TRUE;
end if;
if (BACKTRACK_REPORT) then
EXTERNAL_FILE_MANAGER.GET_BACKTRACK_FILE(BACKTRACK_FILE);
end if;
LASTCCL := 0;
LASTSC := 0;
--initialize the statistics
STARTTIME := MISC.AFLEX_GETTIME;
begin
-- open the skeleton file
if (SKELNAME_USED) then
OPEN(SKELFILE, IN_FILE, STR(SKELNAME));
SKELETON_MANAGER.SET_EXTERNAL_SKELETON;
end if;
exception
when USE_ERROR | NAME_ERROR =>
MISC.AFLEXFATAL("couldn't open skeleton file " & SKELNAME);
end;
-- without a third argument create make an anonymous temp file.
begin
CREATE(TEMP_ACTION_FILE, OUT_FILE);
CREATE(DEF_FILE, OUT_FILE);
exception
when USE_ERROR | NAME_ERROR =>
MISC.AFLEXFATAL("can't create temporary file");
end;
LASTDFA := 0;
LASTNFA := 0;
NUM_RULES := 0;
NUMAS := 0;
NUMSNPAIRS := 0;
TMPUSES := 0;
NUMECS := 0;
NUMEPS := 0;
EPS2 := 0;
NUM_REALLOCS := 0;
HSHCOL := 0;
DFAEQL := 0;
TOTNST := 0;
NUMUNIQ := 0;
NUMDUP := 0;
HSHSAVE := 0;
EOFSEEN := FALSE;
DATAPOS := 0;
DATALINE := 0;
NUM_BACKTRACKING := 0;
ONESP := 0;
NUMPROTS := 0;
VARIABLE_TRAILING_CONTEXT_RULES := FALSE;
BOL_NEEDED := FALSE;
LINENUM := 1;
SECTNUM := 1;
FIRSTPROT := NIL;
-- used in mkprot() so that the first proto goes in slot 1
-- of the proto queue
LASTPROT := 1;
if (USEECS) then
-- set up doubly-linked equivalence classes
ECGROUP(1) := NIL;
for CNT in 2 .. CSIZE loop
ECGROUP(CNT) := CNT - 1;
NEXTECM(CNT - 1) := CNT;
end loop;
NEXTECM(CSIZE) := NIL;
else
-- put everything in its own equivalence class
for CNT in 1 .. CSIZE loop
ECGROUP(CNT) := CNT;
NEXTECM(CNT) := BAD_SUBSCRIPT; -- to catch errors
end loop;
end if;
SET_UP_INITIAL_ALLOCATIONS;
end AFLEXINIT;
-- readin - read in the rules section of the input file(s)
procedure READIN is
begin
SKELETON_MANAGER.SKELOUT;
TEXT_IO.PUT("with " & TSTRING.STR(MISC.BASENAME) & "_dfa" & "; ");
TEXT_IO.PUT_LINE("use " & TSTRING.STR(MISC.BASENAME) & "_dfa" & "; ");
TEXT_IO.PUT("with " & TSTRING.STR(MISC.BASENAME) & "_io" & "; ");
TEXT_IO.PUT_LINE("use " & TSTRING.STR(MISC.BASENAME) & "_io" & "; ");
MISC.LINE_DIRECTIVE_OUT;
PARSER.YYPARSE;
if (USEECS) then
ECS.CRE8ECS(NEXTECM, ECGROUP, CSIZE, NUMECS);
ECS.CCL2ECL;
else
NUMECS := CSIZE;
end if;
exception
when PARSE_TOKENS.SYNTAX_ERROR =>
MISC.AFLEXERROR("fatal parse error at line " & INTEGER'IMAGE(LINENUM));
MAIN_BODY.AFLEXEND(1);
end READIN;
-- set_up_initial_allocations - allocate memory for internal tables
procedure SET_UP_INITIAL_ALLOCATIONS is
begin
CURRENT_MNS := INITIAL_MNS;
FIRSTST := ALLOCATE_INTEGER_ARRAY(CURRENT_MNS);
LASTST := ALLOCATE_INTEGER_ARRAY(CURRENT_MNS);
FINALST := ALLOCATE_INTEGER_ARRAY(CURRENT_MNS);
TRANSCHAR := ALLOCATE_INTEGER_ARRAY(CURRENT_MNS);
TRANS1 := ALLOCATE_INTEGER_ARRAY(CURRENT_MNS);
TRANS2 := ALLOCATE_INTEGER_ARRAY(CURRENT_MNS);
ACCPTNUM := ALLOCATE_INTEGER_ARRAY(CURRENT_MNS);
ASSOC_RULE := ALLOCATE_INTEGER_ARRAY(CURRENT_MNS);
STATE_TYPE := ALLOCATE_STATE_ENUM_ARRAY(CURRENT_MNS);
CURRENT_MAX_RULES := INITIAL_MAX_RULES;
RULE_TYPE := ALLOCATE_RULE_ENUM_ARRAY(CURRENT_MAX_RULES);
RULE_LINENUM := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_RULES);
CURRENT_MAX_SCS := INITIAL_MAX_SCS;
SCSET := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_SCS);
SCBOL := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_SCS);
SCXCLU := ALLOCATE_BOOLEAN_ARRAY(CURRENT_MAX_SCS);
SCEOF := ALLOCATE_BOOLEAN_ARRAY(CURRENT_MAX_SCS);
SCNAME := ALLOCATE_VSTRING_ARRAY(CURRENT_MAX_SCS);
ACTVSC := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_SCS);
CURRENT_MAXCCLS := INITIAL_MAX_CCLS;
CCLMAP := ALLOCATE_INTEGER_ARRAY(CURRENT_MAXCCLS);
CCLLEN := ALLOCATE_INTEGER_ARRAY(CURRENT_MAXCCLS);
CCLNG := ALLOCATE_INTEGER_ARRAY(CURRENT_MAXCCLS);
CURRENT_MAX_CCL_TBL_SIZE := INITIAL_MAX_CCL_TBL_SIZE;
CCLTBL := ALLOCATE_CHARACTER_ARRAY(CURRENT_MAX_CCL_TBL_SIZE);
CURRENT_MAX_DFA_SIZE := INITIAL_MAX_DFA_SIZE;
CURRENT_MAX_XPAIRS := INITIAL_MAX_XPAIRS;
NXT := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_XPAIRS);
CHK := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_XPAIRS);
CURRENT_MAX_TEMPLATE_XPAIRS := INITIAL_MAX_TEMPLATE_XPAIRS;
TNXT := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_TEMPLATE_XPAIRS);
CURRENT_MAX_DFAS := INITIAL_MAX_DFAS;
BASE := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_DFAS);
DEF := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_DFAS);
DFASIZ := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_DFAS);
ACCSIZ := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_DFAS);
DHASH := ALLOCATE_INTEGER_ARRAY(CURRENT_MAX_DFAS);
DSS := ALLOCATE_INT_PTR_ARRAY(CURRENT_MAX_DFAS);
DFAACC := ALLOCATE_DFAACC_UNION(CURRENT_MAX_DFAS);
end SET_UP_INITIAL_ALLOCATIONS;
end MAIN_BODY;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE main body
-- AUTHOR: John Self (UCI)
-- DESCRIPTION driver routines for aflex. Calls drivers for all
-- high level routines from other packages.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/mainS.a,v 1.5 90/01/12 15:20:14 self Exp Locker: self $
-- aflex - tool to generate fast lexical analyzers
package MAIN_BODY is
procedure AFLEXEND(STATUS : in INTEGER);
procedure AFLEXINIT;
procedure READIN;
procedure SET_UP_INITIAL_ALLOCATIONS;
AFLEX_TERMINATE : exception;
TERMINATION_STATUS : INTEGER;
end MAIN_BODY;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE miscellaneous aflex routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION
-- NOTES contains functions used in various places throughout aflex.
-- $Header: /dc/uc/self/arcadia/aflex/ada/src/RCS/miscB.a,v 1.22 1991/07/01 21:30:37 self Exp self $
with MISC_DEFS, TSTRING, TEXT_IO, MISC, MAIN_BODY;
with INT_IO, CALENDAR, EXTERNAL_FILE_MANAGER; use MISC, MISC_DEFS, TEXT_IO,
EXTERNAL_FILE_MANAGER;
package body MISC is
use TSTRING;
-- action_out - write the actions from the temporary file to lex.yy.c
procedure ACTION_OUT is
BUF : VSTRING;
begin
while (not TEXT_IO.END_OF_FILE(TEMP_ACTION_FILE)) loop
TSTRING.GET_LINE(TEMP_ACTION_FILE, BUF);
if ((TSTRING.LEN(BUF) >= 2) and then ((CHAR(BUF, 1) = '%') and (CHAR(BUF,
2) = '%'))) then
exit;
else
TSTRING.PUT_LINE(BUF);
end if;
end loop;
end ACTION_OUT;
-- bubble - bubble sort an integer array in increasing order
--
-- description
-- sorts the first n elements of array v and replaces them in
-- increasing order.
--
-- passed
-- v - the array to be sorted
-- n - the number of elements of 'v' to be sorted
procedure BUBBLE(V : in INT_PTR;
N : in INTEGER) is
K : INTEGER;
begin
for I in reverse 2 .. N loop
for J in 1 .. I - 1 loop
if (V(J) > V(J + 1)) then
-- compare
K := V(J);
-- exchange
V(J) := V(J + 1);
V(J + 1) := K;
end if;
end loop;
end loop;
end BUBBLE;
-- clower - replace upper-case letter to lower-case
function CLOWER(C : in INTEGER) return INTEGER is
begin
if (ISUPPER(CHARACTER'VAL(C))) then
return TOLOWER(C);
else
return C;
end if;
end CLOWER;
-- cshell - shell sort a character array in increasing order
--
-- description
-- does a shell sort of the first n elements of array v.
--
-- passed
-- v - array to be sorted
-- n - number of elements of v to be sorted
procedure CSHELL(V : in out CHAR_ARRAY;
N : in INTEGER) is
GAP, J, JG : INTEGER;
K : CHARACTER;
LOWER_BOUND : INTEGER := V'FIRST;
begin
GAP := N/2;
while GAP > 0 loop
for I in GAP .. N - 1 loop
J := I - GAP;
while (J >= 0) loop
JG := J + GAP;
if (V(J + LOWER_BOUND) <= V(JG + LOWER_BOUND)) then
exit;
end if;
K := V(J + LOWER_BOUND);
V(J + LOWER_BOUND) := V(JG + LOWER_BOUND);
V(JG + LOWER_BOUND) := K;
J := J - GAP;
end loop;
end loop;
GAP := GAP/2;
end loop;
end CSHELL;
-- dataend - finish up a block of data declarations
procedure DATAEND is
begin
if (DATAPOS > 0) then
DATAFLUSH;
-- add terminator for initialization
TEXT_IO.PUT_LINE(" ) ;");
TEXT_IO.NEW_LINE;
DATALINE := 0;
end if;
end DATAEND;
-- dataflush - flush generated data statements
procedure DATAFLUSH(FILE : in FILE_TYPE) is
begin
TEXT_IO.NEW_LINE(FILE);
DATALINE := DATALINE + 1;
if (DATALINE >= NUMDATALINES) then
-- put out a blank line so that the table is grouped into
-- large blocks that enable the user to find elements easily
TEXT_IO.NEW_LINE(FILE);
DATALINE := 0;
end if;
-- reset the number of characters written on the current line
DATAPOS := 0;
end DATAFLUSH;
procedure DATAFLUSH is
begin
DATAFLUSH(CURRENT_OUTPUT);
end DATAFLUSH;
-- aflex_gettime - return current time
function AFLEX_GETTIME return VSTRING is
use TSTRING, CALENDAR;
CURRENT_TIME : TIME;
CURRENT_YEAR : YEAR_NUMBER;
CURRENT_MONTH : MONTH_NUMBER;
CURRENT_DAY : DAY_NUMBER;
CURRENT_SECONDS : DAY_DURATION;
MONTH_STRING, HOUR_STRING, MINUTE_STRING, SECOND_STRING : VSTRING;
HOUR, MINUTE, SECOND : INTEGER;
SECONDS_PER_HOUR : constant
DAY_DURATION := 3600.0;
begin
CURRENT_TIME := CLOCK;
SPLIT(CURRENT_TIME, CURRENT_YEAR, CURRENT_MONTH, CURRENT_DAY,
CURRENT_SECONDS);
case CURRENT_MONTH is
when 1 =>
MONTH_STRING := VSTR("Jan");
when 2 =>
MONTH_STRING := VSTR("Feb");
when 3 =>
MONTH_STRING := VSTR("Mar");
when 4 =>
MONTH_STRING := VSTR("Apr");
when 5 =>
MONTH_STRING := VSTR("May");
when 6 =>
MONTH_STRING := VSTR("Jun");
when 7 =>
MONTH_STRING := VSTR("Jul");
when 8 =>
MONTH_STRING := VSTR("Aug");
when 9 =>
MONTH_STRING := VSTR("Sep");
when 10 =>
MONTH_STRING := VSTR("Oct");
when 11 =>
MONTH_STRING := VSTR("Nov");
when 12 =>
MONTH_STRING := VSTR("Dec");
end case;
HOUR := INTEGER(CURRENT_SECONDS)/INTEGER(SECONDS_PER_HOUR);
MINUTE := INTEGER((CURRENT_SECONDS - (HOUR*SECONDS_PER_HOUR))/60);
SECOND := INTEGER(CURRENT_SECONDS - HOUR*SECONDS_PER_HOUR - MINUTE*60.0);
if (HOUR >= 10) then
HOUR_STRING := VSTR(INTEGER'IMAGE(HOUR));
else
HOUR_STRING := VSTR("0" & INTEGER'IMAGE(HOUR));
end if;
if (MINUTE >= 10) then
MINUTE_STRING := VSTR(INTEGER'IMAGE(MINUTE)(2 .. INTEGER'IMAGE(MINUTE)'
LENGTH));
else
MINUTE_STRING := VSTR("0" & INTEGER'IMAGE(MINUTE)(2 .. INTEGER'IMAGE(
MINUTE)'LENGTH));
end if;
if (SECOND >= 10) then
SECOND_STRING := VSTR(INTEGER'IMAGE(SECOND)(2 .. INTEGER'IMAGE(SECOND)'
LENGTH));
else
SECOND_STRING := VSTR("0" & INTEGER'IMAGE(SECOND)(2 .. INTEGER'IMAGE(
SECOND)'LENGTH));
end if;
return MONTH_STRING & VSTR(INTEGER'IMAGE(CURRENT_DAY)) & HOUR_STRING & ":"
& MINUTE_STRING & ":" & SECOND_STRING & INTEGER'IMAGE(CURRENT_YEAR);
end AFLEX_GETTIME;
-- aflexerror - report an error message and terminate
-- overloaded function, one for vstring, one for string.
procedure AFLEXERROR(MSG : in VSTRING) is
use TEXT_IO;
begin
TSTRING.PUT(STANDARD_ERROR, "aflex: " & MSG);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
MAIN_BODY.AFLEXEND(1);
end AFLEXERROR;
procedure AFLEXERROR(MSG : in STRING) is
use TEXT_IO;
begin
TEXT_IO.PUT(STANDARD_ERROR, "aflex: " & MSG);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
MAIN_BODY.AFLEXEND(1);
end AFLEXERROR;
-- aflexfatal - report a fatal error message and terminate
-- overloaded function, one for vstring, one for string.
procedure AFLEXFATAL(MSG : in VSTRING) is
use TEXT_IO;
begin
TSTRING.PUT(STANDARD_ERROR, "aflex: fatal internal error " & MSG);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
MAIN_BODY.AFLEXEND(1);
end AFLEXFATAL;
procedure AFLEXFATAL(MSG : in STRING) is
use TEXT_IO;
begin
TEXT_IO.PUT(STANDARD_ERROR, "aflex: fatal internal error " & MSG);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
MAIN_BODY.AFLEXEND(1);
end AFLEXFATAL;
-- basename - find the basename of a file
function BASENAME return VSTRING is
END_CHAR_POS : INTEGER := LEN(INFILENAME);
START_CHAR_POS : INTEGER;
begin
if (END_CHAR_POS = 0) then
-- if reading standard input give everything this name
return VSTR("aflex_yy");
end if;
-- find out where the end of the basename is
while ((END_CHAR_POS >= 1) and then
(CHAR(INFILENAME, END_CHAR_POS) /= '.')) loop
END_CHAR_POS := END_CHAR_POS - 1;
end loop;
-- find out where the beginning of the basename is
START_CHAR_POS := END_CHAR_POS; -- start at the end of the basename
while ((START_CHAR_POS > 1) and then
(CHAR(INFILENAME, START_CHAR_POS) /= '/')) loop
START_CHAR_POS := START_CHAR_POS - 1;
end loop;
if (CHAR(INFILENAME, START_CHAR_POS) = '/') then
START_CHAR_POS := START_CHAR_POS + 1;
end if;
if (END_CHAR_POS >= 1) then
return SLICE(INFILENAME, START_CHAR_POS, END_CHAR_POS - 1);
else
return INFILENAME;
end if;
end BASENAME;
-- line_directive_out - spit out a "# line" statement
procedure LINE_DIRECTIVE_OUT(OUTPUT_FILE_NAME : in FILE_TYPE) is
begin
if (GEN_LINE_DIRS) then
TEXT_IO.PUT(OUTPUT_FILE_NAME, "--# line ");
INT_IO.PUT(OUTPUT_FILE_NAME, LINENUM, 1);
TEXT_IO.PUT(OUTPUT_FILE_NAME, " """);
TSTRING.PUT(OUTPUT_FILE_NAME, INFILENAME);
TEXT_IO.PUT_LINE(OUTPUT_FILE_NAME, """");
end if;
end LINE_DIRECTIVE_OUT;
procedure LINE_DIRECTIVE_OUT is
begin
if (GEN_LINE_DIRS) then
TEXT_IO.PUT("--# line ");
INT_IO.PUT(LINENUM, 1);
TEXT_IO.PUT(" """);
TSTRING.PUT(INFILENAME);
TEXT_IO.PUT_LINE("""");
end if;
end LINE_DIRECTIVE_OUT;
-- all_upper - returns true if a string is all upper-case
function ALL_UPPER(STR : in VSTRING) return BOOLEAN is
begin
for I in 1 .. LEN(STR) loop
if (not ((CHAR(STR, I) >= 'A') and (CHAR(STR, I) <= 'Z'))) then
return FALSE;
end if;
end loop;
return TRUE;
end ALL_UPPER;
-- all_lower - returns true if a string is all lower-case
function ALL_LOWER(STR : in VSTRING) return BOOLEAN is
begin
for I in 1 .. LEN(STR) loop
if (not ((CHAR(STR, I) >= 'a') and (CHAR(STR, I) <= 'z'))) then
return FALSE;
end if;
end loop;
return TRUE;
end ALL_LOWER;
-- mk2data - generate a data statement for a two-dimensional array
--
-- generates a data statement initializing the current 2-D array to "value"
procedure MK2DATA(FILE : in FILE_TYPE;
VALUE : in INTEGER) is
begin
if (DATAPOS >= NUMDATAITEMS) then
TEXT_IO.PUT(FILE, ',');
DATAFLUSH(FILE);
end if;
if (DATAPOS = 0) then
-- indent
TEXT_IO.PUT(FILE, " ");
else
TEXT_IO.PUT(FILE, ',');
end if;
DATAPOS := DATAPOS + 1;
INT_IO.PUT(FILE, VALUE, 5);
end MK2DATA;
procedure MK2DATA(VALUE : in INTEGER) is
begin
MK2DATA(CURRENT_OUTPUT, VALUE);
end MK2DATA;
--
-- generates a data statement initializing the current array element to
-- "value"
procedure MKDATA(VALUE : in INTEGER) is
begin
if (DATAPOS >= NUMDATAITEMS) then
TEXT_IO.PUT(',');
DATAFLUSH;
end if;
if (DATAPOS = 0) then
-- indent
TEXT_IO.PUT(" ");
else
TEXT_IO.PUT(',');
end if;
DATAPOS := DATAPOS + 1;
INT_IO.PUT(VALUE, 5);
end MKDATA;
-- myctoi - return the integer represented by a string of digits
function MYCTOI(NUM_ARRAY : in VSTRING) return INTEGER is
TOTAL : INTEGER := 0;
CNT : INTEGER := TSTRING.FIRST;
begin
while (CNT <= TSTRING.LEN(NUM_ARRAY)) loop
TOTAL := TOTAL*10;
TOTAL := TOTAL + CHARACTER'POS(CHAR(NUM_ARRAY, CNT)) - CHARACTER'POS('0')
;
CNT := CNT + 1;
end loop;
return TOTAL;
end MYCTOI;
-- myesc - return character corresponding to escape sequence
function MYESC(ARR : in VSTRING) return CHARACTER is
use TEXT_IO;
begin
case (CHAR(ARR, TSTRING.FIRST + 1)) is
when 'a' =>
return ASCII.BEL;
when 'b' =>
return ASCII.BS;
when 'f' =>
return ASCII.FF;
when 'n' =>
return ASCII.LF;
when 'r' =>
return ASCII.CR;
when 't' =>
return ASCII.HT;
when 'v' =>
return ASCII.VT;
when '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' =>
-- \<octal>
declare
C, ESC_CHAR : CHARACTER;
SPTR : INTEGER := TSTRING.FIRST + 1;
begin
ESC_CHAR := OTOI(TSTRING.SLICE(ARR, TSTRING.FIRST + 1, TSTRING.LEN(ARR
)));
if (ESC_CHAR = ASCII.NUL) then
MISC.SYNERR("escape sequence for null not allowed");
return ASCII.SOH;
end if;
return ESC_CHAR;
end;
when others =>
return CHAR(ARR, TSTRING.FIRST + 1);
end case;
end MYESC;
-- otoi - convert an octal digit string to an integer value
function OTOI(STR : in VSTRING) return CHARACTER is
TOTAL : INTEGER := 0;
CNT : INTEGER := TSTRING.FIRST;
begin
while (CNT <= TSTRING.LEN(STR)) loop
TOTAL := TOTAL*8;
TOTAL := TOTAL + CHARACTER'POS(CHAR(STR, CNT)) - CHARACTER'POS('0');
CNT := CNT + 1;
end loop;
return CHARACTER'VAL(TOTAL);
end OTOI;
-- readable_form - return the the human-readable form of a character
--
-- The returned string is in static storage.
function READABLE_FORM(C : in CHARACTER) return VSTRING is
begin
if ((CHARACTER'POS(C) >= 0 and CHARACTER'POS(C) < 32) or (C = ASCII.DEL))
then
case C is
when ASCII.LF =>
return (VSTR("\n"));
-- Newline
when ASCII.HT =>
return (VSTR("\t"));
-- Horizontal Tab
when ASCII.FF =>
return (VSTR("\f"));
-- Form Feed
when ASCII.CR =>
return (VSTR("\r"));
-- Carriage Return
when ASCII.BS =>
return (VSTR("\b"));
-- Backspace
when others =>
return VSTR("\" & INTEGER'IMAGE(CHARACTER'POS(C)));
end case;
elsif (C = ' ') then
return VSTR("' '");
else
return VSTR(C);
end if;
end READABLE_FORM;
-- transition_struct_out - output a yy_trans_info structure
--
-- outputs the yy_trans_info structure with the two elements, element_v and
-- element_n. Formats the output with spaces and carriage returns.
procedure TRANSITION_STRUCT_OUT(ELEMENT_V, ELEMENT_N : in INTEGER) is
begin
INT_IO.PUT(ELEMENT_V, 7);
TEXT_IO.PUT(", ");
INT_IO.PUT(ELEMENT_N, 5);
TEXT_IO.PUT(",");
DATAPOS := DATAPOS + TRANS_STRUCT_PRINT_LENGTH;
if (DATAPOS >= 75) then
TEXT_IO.NEW_LINE;
DATALINE := DATALINE + 1;
if (DATALINE mod 10 = 0) then
TEXT_IO.NEW_LINE;
end if;
DATAPOS := 0;
end if;
end TRANSITION_STRUCT_OUT;
function SET_YY_TRAILING_HEAD_MASK(SRC : in INTEGER) return INTEGER is
begin
if (CHECK_YY_TRAILING_HEAD_MASK(SRC) = 0) then
return SRC + YY_TRAILING_HEAD_MASK;
else
return SRC;
end if;
end SET_YY_TRAILING_HEAD_MASK;
function CHECK_YY_TRAILING_HEAD_MASK(SRC : in INTEGER) return INTEGER is
begin
if (SRC >= YY_TRAILING_HEAD_MASK) then
return YY_TRAILING_HEAD_MASK;
else
return 0;
end if;
end CHECK_YY_TRAILING_HEAD_MASK;
function SET_YY_TRAILING_MASK(SRC : in INTEGER) return INTEGER is
begin
if (CHECK_YY_TRAILING_MASK(SRC) = 0) then
return SRC + YY_TRAILING_MASK;
else
return SRC;
end if;
end SET_YY_TRAILING_MASK;
function CHECK_YY_TRAILING_MASK(SRC : in INTEGER) return INTEGER is
begin
-- this test is whether both bits are on, or whether onlyy TRAIL_MASK is set
if ((SRC >= YY_TRAILING_HEAD_MASK + YY_TRAILING_MASK) or ((
CHECK_YY_TRAILING_HEAD_MASK(SRC) = 0) and (SRC >= YY_TRAILING_MASK)))
then
return YY_TRAILING_MASK;
else
return 0;
end if;
end CHECK_YY_TRAILING_MASK;
function ISLOWER(C : in CHARACTER) return BOOLEAN is
begin
return (C in 'a' .. 'z');
end ISLOWER;
function ISUPPER(C : in CHARACTER) return BOOLEAN is
begin
return (C in 'A' .. 'Z');
end ISUPPER;
function ISDIGIT(C : in CHARACTER) return BOOLEAN is
begin
return (C in '0' .. '9');
end ISDIGIT;
function TOLOWER(C : in INTEGER) return INTEGER is
begin
return C - CHARACTER'POS('A') + CHARACTER'POS('a');
end TOLOWER;
procedure SYNERR(STR : in STRING) is
use TEXT_IO;
begin
SYNTAXERROR := TRUE;
TEXT_IO.PUT(STANDARD_ERROR, "Syntax error at line ");
INT_IO.PUT(STANDARD_ERROR, LINENUM);
TEXT_IO.PUT(STANDARD_ERROR, STR);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
end SYNERR;
end MISC;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE miscellaneous aflex routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION
-- NOTES contains functions used in various places throughout aflex.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/miscS.a,v 1.9 90/01/12 15:20:19 self Exp Locker: self $
with MISC_DEFS, TSTRING, TEXT_IO;
package MISC is
use MISC_DEFS;
use TSTRING;
use TEXT_IO;
procedure ACTION_OUT;
procedure BUBBLE(V : in INT_PTR;
N : in INTEGER);
function CLOWER(C : in INTEGER) return INTEGER;
procedure CSHELL(V : in out CHAR_ARRAY;
N : in INTEGER);
procedure DATAEND;
procedure DATAFLUSH;
procedure DATAFLUSH(FILE : in FILE_TYPE);
function AFLEX_GETTIME return VSTRING;
procedure AFLEXERROR(MSG : in VSTRING);
procedure AFLEXERROR(MSG : in STRING);
function ALL_UPPER(STR : in VSTRING) return BOOLEAN;
function ALL_LOWER(STR : in VSTRING) return BOOLEAN;
procedure AFLEXFATAL(MSG : in VSTRING);
procedure AFLEXFATAL(MSG : in STRING);
procedure LINE_DIRECTIVE_OUT;
procedure LINE_DIRECTIVE_OUT(OUTPUT_FILE_NAME : in FILE_TYPE);
procedure MK2DATA(VALUE : in INTEGER);
procedure MK2DATA(FILE : in FILE_TYPE;
VALUE : in INTEGER);
procedure MKDATA(VALUE : in INTEGER);
function MYCTOI(NUM_ARRAY : in VSTRING) return INTEGER;
function MYESC(ARR : in VSTRING) return CHARACTER;
function OTOI(STR : in VSTRING) return CHARACTER;
function READABLE_FORM(C : in CHARACTER) return VSTRING;
procedure SYNERR(STR : in STRING);
procedure TRANSITION_STRUCT_OUT(ELEMENT_V, ELEMENT_N : in INTEGER);
function SET_YY_TRAILING_HEAD_MASK(SRC : in INTEGER) return INTEGER;
function CHECK_YY_TRAILING_HEAD_MASK(SRC : in INTEGER) return INTEGER;
function SET_YY_TRAILING_MASK(SRC : in INTEGER) return INTEGER;
function CHECK_YY_TRAILING_MASK(SRC : in INTEGER) return INTEGER;
function ISLOWER(C : in CHARACTER) return BOOLEAN;
function ISUPPER(C : in CHARACTER) return BOOLEAN;
function ISDIGIT(C : in CHARACTER) return BOOLEAN;
function TOLOWER(C : in INTEGER) return INTEGER;
function BASENAME return VSTRING;
end MISC;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE miscellaneous definitions
-- AUTHOR: John Self (UCI)
-- DESCRIPTION contains all global variables used in aflex.
-- also some subprograms which are commonly used.
-- NOTES The real purpose of this file is to contain all miscellaneous
-- items (functions, MACROS, variables definitions) which were at the
-- top level of flex.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/misc_defsB.a,v 1.5 90/01/12 15:20:21 self Exp Locker: self $
package body MISC_DEFS is
-- returns true if an nfa state has an epsilon out-transition slot
-- that can be used. This definition is currently not used.
function FREE_EPSILON(STATE : in INTEGER) return BOOLEAN is
begin
return ((TRANSCHAR(STATE) = SYM_EPSILON) and (TRANS2(STATE) = NO_TRANSITION)
and (FINALST(STATE) /= STATE));
end FREE_EPSILON;
-- returns true if an nfa state has an epsilon out-transition character
-- and both slots are free
function SUPER_FREE_EPSILON(STATE : in INTEGER) return BOOLEAN is
begin
return ((TRANSCHAR(STATE) = SYM_EPSILON) and (TRANS1(STATE) = NO_TRANSITION)
);
end SUPER_FREE_EPSILON;
function ALLOCATE_INTEGER_ARRAY(SIZE : in INTEGER) return INT_PTR is
begin
return new UNBOUNDED_INT_ARRAY(0 .. SIZE);
end ALLOCATE_INTEGER_ARRAY;
procedure REALLOCATE_INTEGER_ARRAY(ARR : in out INT_PTR;
SIZE : in INTEGER) is
NEW_ARR : INT_PTR;
begin
NEW_ARR := ALLOCATE_INTEGER_ARRAY(SIZE);
NEW_ARR(0 .. ARR'LAST) := ARR(0 .. ARR'LAST);
ARR := NEW_ARR;
end REALLOCATE_INTEGER_ARRAY;
procedure REALLOCATE_STATE_ENUM_ARRAY(ARR : in out STATE_ENUM_PTR;
SIZE : in INTEGER) is
NEW_ARR : STATE_ENUM_PTR;
begin
NEW_ARR := ALLOCATE_STATE_ENUM_ARRAY(SIZE);
NEW_ARR(0 .. ARR'LAST) := ARR(0 .. ARR'LAST);
ARR := NEW_ARR;
end REALLOCATE_STATE_ENUM_ARRAY;
procedure REALLOCATE_RULE_ENUM_ARRAY(ARR : in out RULE_ENUM_PTR;
SIZE : in INTEGER) is
NEW_ARR : RULE_ENUM_PTR;
begin
NEW_ARR := ALLOCATE_RULE_ENUM_ARRAY(SIZE);
NEW_ARR(0 .. ARR'LAST) := ARR(0 .. ARR'LAST);
ARR := NEW_ARR;
end REALLOCATE_RULE_ENUM_ARRAY;
function ALLOCATE_INT_PTR_ARRAY(SIZE : in INTEGER) return INT_STAR_PTR is
begin
return new UNBOUNDED_INT_STAR_ARRAY(0 .. SIZE);
end ALLOCATE_INT_PTR_ARRAY;
function ALLOCATE_RULE_ENUM_ARRAY(SIZE : in INTEGER) return RULE_ENUM_PTR is
begin
return new UNBOUNDED_RULE_ENUM_ARRAY(0 .. SIZE);
end ALLOCATE_RULE_ENUM_ARRAY;
function ALLOCATE_STATE_ENUM_ARRAY(SIZE : in INTEGER) return STATE_ENUM_PTR
is
begin
return new UNBOUNDED_STATE_ENUM_ARRAY(0 .. SIZE);
end ALLOCATE_STATE_ENUM_ARRAY;
function ALLOCATE_BOOLEAN_ARRAY(SIZE : in INTEGER) return BOOLEAN_PTR is
begin
return new BOOLEAN_ARRAY(0 .. SIZE);
end ALLOCATE_BOOLEAN_ARRAY;
function ALLOCATE_VSTRING_ARRAY(SIZE : in INTEGER) return VSTRING_PTR is
begin
return new UNBOUNDED_VSTRING_ARRAY(0 .. SIZE);
end ALLOCATE_VSTRING_ARRAY;
function ALLOCATE_DFAACC_UNION(SIZE : in INTEGER) return DFAACC_PTR is
begin
return new UNBOUNDED_DFAACC_ARRAY(0 .. SIZE);
end ALLOCATE_DFAACC_UNION;
procedure REALLOCATE_INT_PTR_ARRAY(ARR : in out INT_STAR_PTR;
SIZE : in INTEGER) is
NEW_ARR : INT_STAR_PTR;
begin
NEW_ARR := ALLOCATE_INT_PTR_ARRAY(SIZE);
NEW_ARR(0 .. ARR'LAST) := ARR(0 .. ARR'LAST);
ARR := NEW_ARR;
end REALLOCATE_INT_PTR_ARRAY;
procedure REALLOCATE_CHARACTER_ARRAY(ARR : in out CHAR_PTR;
SIZE : in INTEGER) is
NEW_ARR : CHAR_PTR;
begin
NEW_ARR := ALLOCATE_CHARACTER_ARRAY(SIZE);
NEW_ARR(0 .. ARR'LAST) := ARR(0 .. ARR'LAST);
ARR := NEW_ARR;
end REALLOCATE_CHARACTER_ARRAY;
procedure REALLOCATE_VSTRING_ARRAY(ARR : in out VSTRING_PTR;
SIZE : in INTEGER) is
NEW_ARR : VSTRING_PTR;
begin
NEW_ARR := ALLOCATE_VSTRING_ARRAY(SIZE);
NEW_ARR(0 .. ARR'LAST) := ARR(0 .. ARR'LAST);
ARR := NEW_ARR;
end REALLOCATE_VSTRING_ARRAY;
function ALLOCATE_CHARACTER_ARRAY(SIZE : in INTEGER) return CHAR_PTR is
begin
return new CHAR_ARRAY(0 .. SIZE);
end ALLOCATE_CHARACTER_ARRAY;
procedure REALLOCATE_DFAACC_UNION(ARR : in out DFAACC_PTR;
SIZE : in INTEGER) is
NEW_ARR : DFAACC_PTR;
begin
NEW_ARR := ALLOCATE_DFAACC_UNION(SIZE);
NEW_ARR(0 .. ARR'LAST) := ARR(0 .. ARR'LAST);
ARR := NEW_ARR;
end REALLOCATE_DFAACC_UNION;
procedure REALLOCATE_BOOLEAN_ARRAY(ARR : in out BOOLEAN_PTR;
SIZE : in INTEGER) is
NEW_ARR : BOOLEAN_PTR;
begin
NEW_ARR := ALLOCATE_BOOLEAN_ARRAY(SIZE);
NEW_ARR(0 .. ARR'LAST) := ARR(0 .. ARR'LAST);
ARR := NEW_ARR;
end REALLOCATE_BOOLEAN_ARRAY;
function MAX(X, Y : in INTEGER) return INTEGER is
begin
if (X > Y) then
return X;
else
return Y;
end if;
end MAX;
function MIN(X, Y : in INTEGER) return INTEGER is
begin
if (X < Y) then
return X;
else
return Y;
end if;
end MIN;
end MISC_DEFS;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE miscellaneous definitions
-- AUTHOR: John Self (UCI)
-- DESCRIPTION contains all global variables used in aflex.
-- also some subprograms which are commonly used.
-- NOTES The real purpose of this file is to contain all miscellaneous
-- items (functions, MACROS, variables definitions) which were at the
-- top level of flex.
-- $Header: /co/ua/self/arcadia/alex/ada/RCS/misc_defsS.a,v 1.8 90/01/04 13:39:
-- 33 self Exp Locker: self $
with TEXT_IO, TSTRING;
use TEXT_IO, TSTRING;
package MISC_DEFS is
-- various definitions that were in parse.y
PAT, SCNUM, EPS, HEADCNT, TRAILCNT, ANYCCL, LASTCHAR, ACTVP, RULELEN : INTEGER
;
TRLCONTXT, XCLUFLG, CCLSORTED, VARLENGTH, VARIABLE_TRAIL_RULE : BOOLEAN;
MADEANY : BOOLEAN := FALSE; -- whether we've made the '.' character class
PREVIOUS_CONTINUED_ACTION : BOOLEAN; -- whether the previous rule's action wa
-- s '|'
-- maximum line length we'll have to deal with
MAXLINE : constant INTEGER := 1024;
-- These typees are needed for the various allocators.
type UNBOUNDED_INT_ARRAY is array ( INTEGER range <> ) of INTEGER;
type INT_PTR is access UNBOUNDED_INT_ARRAY;
type INT_STAR is access INTEGER;
type UNBOUNDED_INT_STAR_ARRAY is array ( INTEGER range <> ) of INT_PTR;
type INT_STAR_PTR is access UNBOUNDED_INT_STAR_ARRAY;
type UNBOUNDED_VSTRING_ARRAY is array ( INTEGER range <> ) of VSTRING;
type VSTRING_PTR is access UNBOUNDED_VSTRING_ARRAY;
type BOOLEAN_ARRAY is array ( INTEGER range <> ) of BOOLEAN;
type BOOLEAN_PTR is access BOOLEAN_ARRAY;
type CHAR_ARRAY is array ( INTEGER range <> ) of CHARACTER;
type CHAR_PTR is access CHAR_ARRAY;
-- different types of states; values are useful as masks, as well, for
-- routines like check_trailing_context()
type STATE_ENUM is (STATE_NORMAL, STATE_TRAILING_CONTEXT);
type UNBOUNDED_STATE_ENUM_ARRAY is array ( INTEGER range <> ) of STATE_ENUM;
type STATE_ENUM_PTR is access UNBOUNDED_STATE_ENUM_ARRAY;
-- different types of rules
type RULE_ENUM is (RULE_NORMAL, RULE_VARIABLE);
type UNBOUNDED_RULE_ENUM_ARRAY is array ( INTEGER range <> ) of RULE_ENUM;
type RULE_ENUM_PTR is access UNBOUNDED_RULE_ENUM_ARRAY;
type DFAACC_TYPE is
record
DFAACC_SET : INT_PTR;
DFAACC_STATE : INTEGER;
end record;
type UNBOUNDED_DFAACC_ARRAY is array ( INTEGER range <> ) of DFAACC_TYPE;
type DFAACC_PTR is access UNBOUNDED_DFAACC_ARRAY;
-- maximum size of file name
FILENAMESIZE : constant INTEGER := 1024;
function MIN (X, Y : in INTEGER) return INTEGER;
function MAX (X, Y : in INTEGER) return INTEGER;
-- special chk[] values marking the slots taking by end-of-buffer and action
-- numbers
EOB_POSITION : constant INTEGER := - 1;
ACTION_POSITION : constant INTEGER := - 2;
-- number of data items per line for -f output
NUMDATAITEMS : constant INTEGER := 10;
-- number of lines of data in -f output before inserting a blank line for
-- readability.
NUMDATALINES : constant INTEGER := 10;
-- transition_struct_out() definitions
TRANS_STRUCT_PRINT_LENGTH : constant INTEGER := 15;
-- returns true if an nfa state has an epsilon out-transition slot
-- that can be used. This definition is currently not used.
function FREE_EPSILON ( STATE : in INTEGER) return BOOLEAN;
-- returns true if an nfa state has an epsilon out-transition character
-- and both slots are free
function SUPER_FREE_EPSILON (STATE : in INTEGER) return BOOLEAN;
-- maximum number of NFA states that can comprise a DFA state. It's real
-- big because if there's a lot of rules, the initial state will have a
-- huge epsilon closure.
INITIAL_MAX_DFA_SIZE : constant INTEGER := 750;
MAX_DFA_SIZE_INCREMENT : constant INTEGER := 750;
-- a note on the following masks. They are used to mark accepting numbers
-- as being special. As such, they implicitly limit the number of accepting
-- numbers (i.e., rules) because if there are too many rules the rule numbers
-- will overload the mask bits. Fortunately, this limit is \large/ (0x2000 ==
-- 8192) so unlikely to actually cause any problems. A check is made in
-- new_rule() to ensure that this limit is not reached.
-- mask to mark a trailing context accepting number
-- #define YY_TRAILING_MASK 0x2000
YY_TRAILING_MASK : constant INTEGER := 16#2000#;
-- mask to mark the accepting number of the "head" of a trailing context rule
-- #define YY_TRAILING_HEAD_MASK 0x4000
YY_TRAILING_HEAD_MASK : constant INTEGER := 16#4000#;
-- maximum number of rules, as outlined in the above note
MAX_RULE : constant INTEGER := YY_TRAILING_MASK - 1;
-- NIL must be 0. If not, its special meaning when making equivalence classes
-- (it marks the representative of a given e.c.) will be unidentifiable
NIL : constant INTEGER := 0;
JAM : constant INTEGER := - 1; -- to mark a missing DFA transition
NO_TRANSITION : constant INTEGER := NIL;
UNIQUE : constant INTEGER := - 1; -- marks a symbol as an e.c. representative
INFINITY : constant INTEGER := - 1; -- for x{5,} constructions
-- size of input alphabet - should be size of ASCII set
CSIZE : constant INTEGER := 127;
INITIAL_MAX_CCLS : constant INTEGER := 100; -- max number of unique character
-- classes
MAX_CCLS_INCREMENT : constant INTEGER := 100;
-- size of table holding members of character classes
INITIAL_MAX_CCL_TBL_SIZE : constant INTEGER := 500;
MAX_CCL_TBL_SIZE_INCREMENT : constant INTEGER := 250;
INITIAL_MAX_RULES : constant INTEGER := 100;
-- default maximum number of rules
MAX_RULES_INCREMENT : constant INTEGER := 100;
INITIAL_MNS : constant INTEGER := 2000; -- default maximum number of nfa stat
-- es
MNS_INCREMENT : constant INTEGER := 1000; -- amount to bump above by if it's
-- not enough
INITIAL_MAX_DFAS : constant INTEGER := 1000; -- default maximum number of dfa
-- states
MAX_DFAS_INCREMENT : constant INTEGER := 1000;
JAMSTATE_CONST : constant INTEGER := - 32766; -- marks a reference to the sta
-- te that always jams
-- enough so that if it's subtracted from an NFA state number, the result
-- is guaranteed to be negative
MARKER_DIFFERENCE : constant INTEGER := 32000;
MAXIMUM_MNS : constant INTEGER := 31999;
-- maximum number of nxt/chk pairs for non-templates
INITIAL_MAX_XPAIRS : constant INTEGER := 2000;
MAX_XPAIRS_INCREMENT : constant INTEGER := 2000;
-- maximum number of nxt/chk pairs needed for templates
INITIAL_MAX_TEMPLATE_XPAIRS : constant INTEGER := 2500;
MAX_TEMPLATE_XPAIRS_INCREMENT : constant INTEGER := 2500;
SYM_EPSILON : constant INTEGER := 0; -- to mark transitions on the symbol eps
-- ilon
INITIAL_MAX_SCS : constant INTEGER := 40; -- maximum number of start conditio
-- ns
MAX_SCS_INCREMENT : constant INTEGER := 40; -- amount to bump by if it's not
-- enough
ONE_STACK_SIZE : constant INTEGER := 500; -- stack of states with only one ou
-- t-transition
SAME_TRANS : constant INTEGER := - 1; -- transition is the same as "default"
-- entry for state
-- the following percentages are used to tune table compression:
--
-- the percentage the number of out-transitions a state must be of the
-- number of equivalence classes in order to be considered for table
-- compaction by using protos
PROTO_SIZE_PERCENTAGE : constant INTEGER := 15;
-- the percentage the number of homogeneous out-transitions of a state
-- must be of the number of total out-transitions of the state in order
-- that the state's transition table is first compared with a potential
-- template of the most common out-transition instead of with the first
--proto in the proto queue
CHECK_COM_PERCENTAGE : constant INTEGER := 50;
-- the percentage the number of differences between a state's transition
-- table and the proto it was first compared with must be of the total
-- number of out-transitions of the state in order to keep the first
-- proto as a good match and not search any further
FIRST_MATCH_DIFF_PERCENTAGE : constant INTEGER := 10;
-- the percentage the number of differences between a state's transition
-- table and the most similar proto must be of the state's total number
-- of out-transitions to use the proto as an acceptable close match
ACCEPTABLE_DIFF_PERCENTAGE : constant INTEGER := 50;
-- the percentage the number of homogeneous out-transitions of a state
-- must be of the number of total out-transitions of the state in order
-- to consider making a template from the state
TEMPLATE_SAME_PERCENTAGE : constant INTEGER := 60;
-- the percentage the number of differences between a state's transition
-- table and the most similar proto must be of the state's total number
-- of out-transitions to create a new proto from the state
NEW_PROTO_DIFF_PERCENTAGE : constant INTEGER := 20;
-- the percentage the total number of out-transitions of a state must be
-- of the number of equivalence classes in order to consider trying to
-- fit the transition table into "holes" inside the nxt/chk table.
INTERIOR_FIT_PERCENTAGE : constant INTEGER := 15;
-- size of region set aside to cache the complete transition table of
-- protos on the proto queue to enable quick comparisons
PROT_SAVE_SIZE : constant INTEGER := 2000;
MSP : constant INTEGER := 50; -- maximum number of saved protos (protos on th
-- e proto queue)
-- maximum number of out-transitions a state can have that we'll rummage
-- around through the interior of the internal fast table looking for a
-- spot for it
MAX_XTIONS_FULL_INTERIOR_FIT : constant INTEGER := 4;
-- maximum number of rules which will be reported as being associated
-- with a DFA state
MAX_ASSOC_RULES : constant INTEGER := 100;
-- number that, if used to subscript an array, has a good chance of producing
-- an error; should be small enough to fit into a short
BAD_SUBSCRIPT : constant INTEGER := - 32767;
-- Declarations for global variables.
-- variables for symbol tables:
-- sctbl - start-condition symbol table
-- ndtbl - name-definition symbol table
-- ccltab - character class text symbol table
type HASH_ENTRY;
type HASH_LINK is access HASH_ENTRY;
type HASH_ENTRY is
record
PREV, NEXT : HASH_LINK;
NAME, STR_VAL : VSTRING;
INT_VAL : INTEGER;
end record;
type HASH_TABLE is array ( INTEGER range <> ) of HASH_LINK;
NAME_TABLE_HASH_SIZE : constant INTEGER := 101;
START_COND_HASH_SIZE : constant INTEGER := 101;
CCL_HASH_SIZE : constant INTEGER := 101;
subtype NDTBL_TYPE is HASH_TABLE (0 .. NAME_TABLE_HASH_SIZE - 1);
NDTBL : NDTBL_TYPE;
subtype SCTBL_TYPE is HASH_TABLE (0 .. START_COND_HASH_SIZE - 1);
SCTBL : SCTBL_TYPE;
subtype CCLTAB_TYPE is HASH_TABLE (0 .. CCL_HASH_SIZE);
CCLTAB : CCLTAB_TYPE;
-- variables for flags:
-- printstats - if true (-v), dump statistics
-- syntaxerror - true if a syntax error has been found
-- eofseen - true if we've seen an eof in the input file
-- ddebug - if true (-d), make a "debug" scanner
-- trace - if true (-T), trace processing
-- spprdflt - if true (-s), suppress the default rule
-- interactive - if true (-I), generate an interactive scanner
-- caseins - if true (-i), generate a case-insensitive scanner
-- useecs - if true (-ce flag), use equivalence classes
-- fulltbl - if true (-cf flag), don't compress the DFA state table
-- usemecs - if true (-cm flag), use meta-equivalence classes
-- gen_line_dirs - if true (i.e., no -L flag), generate #line directives
-- performance_report - if true (i.e., -p flag), generate a report relating
-- to scanner performance
-- backtrack_report - if true (i.e., -b flag), generate "lex.backtrack" file
-- listing backtracking states
-- continued_action - true if this rule's action is to "fall through" to
-- the next rule's action (i.e., the '|' action)
PRINTSTATS, DDEBUG, SPPRDFLT,
INTERACTIVE, CASEINS, USEECS, FULLTBL, USEMECS,
GEN_LINE_DIRS, PERFORMANCE_REPORT, BACKTRACK_REPORT,
TRACE, EOFSEEN, CONTINUED_ACTION : BOOLEAN;
SYNTAXERROR : BOOLEAN;
-- variables used in the aflex input routines:
-- datapos - characters on current output line
-- dataline - number of contiguous lines of data in current data
-- statement. Used to generate readable -f output
-- skelfile - the skeleton file
-- yyin - input file
-- temp_action_file - temporary file to hold actions
-- backtrack_file - file to summarize backtracking states to
-- infilename - name of input file
-- linenum - current input line number
DATAPOS, DATALINE, LINENUM : INTEGER;
SKELFILE, YYIN, TEMP_ACTION_FILE, BACKTRACK_FILE, DEF_FILE : FILE_TYPE;
INFILENAME : VSTRING;
-- variables for stack of states having only one out-transition:
-- onestate - state number
-- onesym - transition symbol
-- onenext - target state
-- onedef - default base entry
-- onesp - stack pointer
ONESTATE, ONESYM, ONENEXT, ONEDEF : array (0 .. ONE_STACK_SIZE - 1) of INTEGER
;
ONESP : INTEGER;
-- variables for nfa machine data:
-- current_mns - current maximum on number of NFA states
-- num_rules - number of the last accepting state; also is number of
-- rules created so far
-- current_max_rules - current maximum number of rules
-- lastnfa - last nfa state number created
-- firstst - physically the first state of a fragment
-- lastst - last physical state of fragment
-- finalst - last logical state of fragment
-- transchar - transition character
-- trans1 - transition state
-- trans2 - 2nd transition state for epsilons
-- accptnum - accepting number
-- assoc_rule - rule associated with this NFA state (or 0 if none)
-- state_type - a STATE_xxx type identifying whether the state is part
-- of a normal rule, the leading state in a trailing context
-- rule (i.e., the state which marks the transition from
-- recognizing the text-to-be-matched to the beginning of
-- the trailing context), or a subsequent state in a trailing
-- context rule
-- rule_type - a RULE_xxx type identifying whether this a a ho-hum
-- normal rule or one which has variable head & trailing
-- context
-- rule_linenum - line number associated with rule
CURRENT_MNS, NUM_RULES, CURRENT_MAX_RULES, LASTNFA : INTEGER;
FIRSTST, LASTST, FINALST, TRANSCHAR, TRANS1, TRANS2 : INT_PTR;
ACCPTNUM, ASSOC_RULE, RULE_LINENUM : INT_PTR;
RULE_TYPE : RULE_ENUM_PTR;
STATE_TYPE : STATE_ENUM_PTR;
-- global holding current type of state we're making
CURRENT_STATE_ENUM : STATE_ENUM;
-- true if the input rules include a rule with both variable-length head
-- and trailing context, false otherwise
VARIABLE_TRAILING_CONTEXT_RULES : BOOLEAN;
-- variables for protos:
-- numtemps - number of templates created
-- numprots - number of protos created
-- protprev - backlink to a more-recently used proto
-- protnext - forward link to a less-recently used proto
-- prottbl - base/def table entry for proto
-- protcomst - common state of proto
-- firstprot - number of the most recently used proto
-- lastprot - number of the least recently used proto
-- protsave contains the entire state array for protos
NUMTEMPS, NUMPROTS, FIRSTPROT, LASTPROT : INTEGER;
PROTPREV, PROTNEXT, PROTTBL, PROTCOMST : array (0 .. MSP - 1) of INTEGER;
PROTSAVE : array (0 .. PROT_SAVE_SIZE - 1) of INTEGER;
-- variables for managing equivalence classes:
-- numecs - number of equivalence classes
-- nextecm - forward link of Equivalence Class members
-- ecgroup - class number or backward link of EC members
-- nummecs - number of meta-equivalence classes (used to compress
-- templates)
-- tecfwd - forward link of meta-equivalence classes members
-- * tecbck - backward link of MEC's
NUMECS, NUMMECS : INTEGER;
subtype C_SIZE_ARRAY is UNBOUNDED_INT_ARRAY (0 .. CSIZE);
type C_SIZE_BOOL_ARRAY is array (0 .. CSIZE) of BOOLEAN;
NEXTECM, ECGROUP, TECFWD, TECBCK : C_SIZE_ARRAY;
-- variables for start conditions:
-- lastsc - last start condition created
-- current_max_scs - current limit on number of start conditions
-- scset - set of rules active in start condition
-- scbol - set of rules active only at the beginning of line in a s.c.
-- scxclu - true if start condition is exclusive
-- sceof - true if start condition has EOF rule
-- scname - start condition name
-- actvsc - stack of active start conditions for the current rule
LASTSC, CURRENT_MAX_SCS : INTEGER;
SCSET, SCBOL : INT_PTR;
SCXCLU, SCEOF : BOOLEAN_PTR;
ACTVSC : INT_PTR;
SCNAME : VSTRING_PTR;
-- variables for dfa machine data:
-- current_max_dfa_size - current maximum number of NFA states in DFA
-- current_max_xpairs - current maximum number of non-template xtion pairs
-- current_max_template_xpairs - current maximum number of template pairs
-- current_max_dfas - current maximum number DFA states
-- lastdfa - last dfa state number created
-- nxt - state to enter upon reading character
-- chk - check value to see if "nxt" applies
-- tnxt - internal nxt table for templates
-- base - offset into "nxt" for given state
-- def - where to go if "chk" disallows "nxt" entry
-- tblend - last "nxt/chk" table entry being used
-- firstfree - first empty entry in "nxt/chk" table
-- dss - nfa state set for each dfa
-- dfasiz - size of nfa state set for each dfa
-- dfaacc - accepting set for each dfa state (or accepting number, if
-- -r is not given)
-- accsiz - size of accepting set for each dfa state
-- dhash - dfa state hash value
-- numas - number of DFA accepting states created; note that this
-- is not necessarily the same value as num_rules, which is the analogous
-- value for the NFA
-- numsnpairs - number of state/nextstate transition pairs
-- jambase - position in base/def where the default jam table starts
-- jamstate - state number corresponding to "jam" state
-- end_of_buffer_state - end-of-buffer dfa state number
CURRENT_MAX_DFA_SIZE, CURRENT_MAX_XPAIRS : INTEGER;
CURRENT_MAX_TEMPLATE_XPAIRS, CURRENT_MAX_DFAS : INTEGER;
LASTDFA, LASTTEMP : INTEGER;
NXT, CHK, TNXT : INT_PTR;
BASE, DEF , DFASIZ : INT_PTR;
TBLEND, FIRSTFREE : INTEGER;
DSS : INT_STAR_PTR;
DFAACC : DFAACC_PTR;
-- type declaration for dfaacc_type moved above
ACCSIZ, DHASH : INT_PTR;
END_OF_BUFFER_STATE, NUMSNPAIRS, JAMBASE, JAMSTATE, NUMAS : INTEGER;
-- variables for ccl information:
-- lastccl - ccl index of the last created ccl
-- current_maxccls - current limit on the maximum number of unique ccl's
-- cclmap - maps a ccl index to its set pointer
-- ccllen - gives the length of a ccl
-- cclng - true for a given ccl if the ccl is negated
-- cclreuse - counts how many times a ccl is re-used
-- current_max_ccl_tbl_size - current limit on number of characters needed
-- to represent the unique ccl's
-- ccltbl - holds the characters in each ccl - indexed by cclmap
CURRENT_MAX_CCL_TBL_SIZE, LASTCCL, CURRENT_MAXCCLS, CCLREUSE : INTEGER;
CCLMAP, CCLLEN, CCLNG : INT_PTR;
CCLTBL : CHAR_PTR;
-- variables for miscellaneous information:
-- starttime - real-time when we started
-- endtime - real-time when we ended
-- nmstr - last NAME scanned by the scanner
-- sectnum - section number currently being parsed
-- nummt - number of empty nxt/chk table entries
-- hshcol - number of hash collisions detected by snstods
-- dfaeql - number of times a newly created dfa was equal to an old one
-- numeps - number of epsilon NFA states created
-- eps2 - number of epsilon states which have 2 out-transitions
-- num_reallocs - number of times it was necessary to realloc() a group
-- of arrays
-- tmpuses - number of DFA states that chain to templates
-- totnst - total number of NFA states used to make DFA states
-- peakpairs - peak number of transition pairs we had to store internally
-- numuniq - number of unique transitions
-- numdup - number of duplicate transitions
-- hshsave - number of hash collisions saved by checking number of states
-- num_backtracking - number of DFA states requiring back-tracking
-- bol_needed - whether scanner needs beginning-of-line recognition
NMSTR : VSTRING;
SECTNUM, NUMMT, HSHCOL, DFAEQL, NUMEPS, EPS2, NUM_REALLOCS : INTEGER;
TMPUSES, TOTNST, PEAKPAIRS, NUMUNIQ, NUMDUP, HSHSAVE : INTEGER;
NUM_BACKTRACKING : INTEGER;
BOL_NEEDED : BOOLEAN;
function ALLOCATE_INTEGER_ARRAY (SIZE : in INTEGER) return INT_PTR;
function ALLOCATE_INT_PTR_ARRAY (SIZE : in INTEGER) return INT_STAR_PTR;
function ALLOCATE_VSTRING_ARRAY (SIZE : in INTEGER) return VSTRING_PTR;
function ALLOCATE_DFAACC_UNION (SIZE : in INTEGER) return DFAACC_PTR;
function ALLOCATE_CHARACTER_ARRAY (SIZE : in INTEGER) return CHAR_PTR;
function ALLOCATE_RULE_ENUM_ARRAY (SIZE : in INTEGER) return RULE_ENUM_PTR;
function ALLOCATE_STATE_ENUM_ARRAY (SIZE : in INTEGER) return STATE_ENUM_PTR;
function ALLOCATE_BOOLEAN_ARRAY (SIZE : in INTEGER) return BOOLEAN_PTR;
procedure REALLOCATE_INTEGER_ARRAY (ARR : in out INT_PTR;
SIZE : in INTEGER);
procedure REALLOCATE_INT_PTR_ARRAY (ARR : in out INT_STAR_PTR;
SIZE : in INTEGER);
procedure REALLOCATE_VSTRING_ARRAY (ARR : in out VSTRING_PTR;
SIZE : in INTEGER);
procedure REALLOCATE_DFAACC_UNION (ARR : in out DFAACC_PTR;
SIZE : in INTEGER);
procedure REALLOCATE_CHARACTER_ARRAY (ARR : in out CHAR_PTR;
SIZE : in INTEGER);
procedure REALLOCATE_RULE_ENUM_ARRAY (ARR : in out RULE_ENUM_PTR;
SIZE : in INTEGER);
procedure REALLOCATE_STATE_ENUM_ARRAY (ARR : in out STATE_ENUM_PTR;
SIZE : in INTEGER);
procedure REALLOCATE_BOOLEAN_ARRAY (ARR : in out BOOLEAN_PTR;
SIZE : in INTEGER);
end MISC_DEFS;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE NFA construction routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION builds the NFA.
-- NOTES this file mirrors flex as closely as possible.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/nfaB.a,v 1.6 90/01/12 15:20:27 self Exp Locker: self $
with MISC_DEFS, NFA, MISC, ECS;
with TSTRING, INT_IO, TEXT_IO, EXTERNAL_FILE_MANAGER; use MISC_DEFS, TSTRING,
EXTERNAL_FILE_MANAGER;
package body NFA is
-- add_accept - add an accepting state to a machine
--
-- accepting_number becomes mach's accepting number.
procedure ADD_ACCEPT(MACH : in out INTEGER;
ACCEPTING_NUMBER : in INTEGER) is
-- hang the accepting number off an epsilon state. if it is associated
-- with a state that has a non-epsilon out-transition, then the state
-- will accept BEFORE it makes that transition, i.e., one character
-- too soon
ASTATE : INTEGER;
begin
if (TRANSCHAR(FINALST(MACH)) = SYM_EPSILON) then
ACCPTNUM(FINALST(MACH)) := ACCEPTING_NUMBER;
else
ASTATE := MKSTATE(SYM_EPSILON);
ACCPTNUM(ASTATE) := ACCEPTING_NUMBER;
MACH := LINK_MACHINES(MACH, ASTATE);
end if;
end ADD_ACCEPT;
-- copysingl - make a given number of copies of a singleton machine
--
-- newsng - a new singleton composed of num copies of singl
-- singl - a singleton machine
-- num - the number of copies of singl to be present in newsng
function COPYSINGL(SINGL, NUM : in INTEGER) return INTEGER is
COPY : INTEGER;
begin
COPY := MKSTATE(SYM_EPSILON);
for I in 1 .. NUM loop
COPY := LINK_MACHINES(COPY, DUPMACHINE(SINGL));
end loop;
return COPY;
end COPYSINGL;
-- dumpnfa - debugging routine to write out an nfa
procedure DUMPNFA(STATE1 : in INTEGER) is
SYM, TSP1, TSP2, ANUM : INTEGER;
use TEXT_IO;
begin
TEXT_IO.NEW_LINE(STANDARD_ERROR);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
TEXT_IO.PUT(STANDARD_ERROR,
"********** beginning dump of nfa with start state ");
INT_IO.PUT(STANDARD_ERROR, STATE1, 0);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
-- we probably should loop starting at firstst[state1] and going to
-- lastst[state1], but they're not maintained properly when we "or"
-- all of the rules together. So we use our knowledge that the machine
-- starts at state 1 and ends at lastnfa.
for NS in 1 .. LASTNFA loop
TEXT_IO.PUT(STANDARD_ERROR, "state # ");
INT_IO.PUT(STANDARD_ERROR, NS, 4);
TEXT_IO.PUT(ASCII.HT);
SYM := TRANSCHAR(NS);
TSP1 := TRANS1(NS);
TSP2 := TRANS2(NS);
ANUM := ACCPTNUM(NS);
INT_IO.PUT(STANDARD_ERROR, SYM, 5);
TEXT_IO.PUT(STANDARD_ERROR, ": ");
INT_IO.PUT(STANDARD_ERROR, TSP1, 4);
TEXT_IO.PUT(STANDARD_ERROR, ",");
INT_IO.PUT(STANDARD_ERROR, TSP2, 4);
if (ANUM /= NIL) then
TEXT_IO.PUT(STANDARD_ERROR, " [");
INT_IO.PUT(STANDARD_ERROR, ANUM, 0);
TEXT_IO.PUT(STANDARD_ERROR, "]");
end if;
TEXT_IO.NEW_LINE(STANDARD_ERROR);
end loop;
TEXT_IO.PUT(STANDARD_ERROR, "********** end of dump");
TEXT_IO.NEW_LINE(STANDARD_ERROR);
end DUMPNFA;
-- dupmachine - make a duplicate of a given machine
--
-- copy - holds duplicate of mach
-- mach - machine to be duplicated
--
-- note that the copy of mach is NOT an exact duplicate; rather, all the
-- transition states values are adjusted so that the copy is self-contained,
-- as the original should have been.
--
-- also note that the original MUST be contiguous, with its low and high
-- states accessible by the arrays firstst and lastst
function DUPMACHINE(MACH : in INTEGER) return INTEGER is
INIT, STATE_OFFSET : INTEGER;
STATE : INTEGER := 0;
LAST : INTEGER := LASTST(MACH);
I : INTEGER;
begin
I := FIRSTST(MACH);
while (I <= LAST) loop
STATE := MKSTATE(TRANSCHAR(I));
if (TRANS1(I) /= NO_TRANSITION) then
MKXTION(FINALST(STATE), TRANS1(I) + STATE - I);
if ((TRANSCHAR(I) = SYM_EPSILON) and (TRANS2(I) /= NO_TRANSITION)) then
MKXTION(FINALST(STATE), TRANS2(I) + STATE - I);
end if;
end if;
ACCPTNUM(STATE) := ACCPTNUM(I);
I := I + 1;
end loop;
if (STATE = 0) then
MISC.AFLEXFATAL("empty machine in dupmachine()");
end if;
STATE_OFFSET := STATE - I + 1;
INIT := MACH + STATE_OFFSET;
FIRSTST(INIT) := FIRSTST(MACH) + STATE_OFFSET;
FINALST(INIT) := FINALST(MACH) + STATE_OFFSET;
LASTST(INIT) := LASTST(MACH) + STATE_OFFSET;
return INIT;
end DUPMACHINE;
-- finish_rule - finish up the processing for a rule
--
-- An accepting number is added to the given machine. If variable_trail_rule
-- is true then the rule has trailing context and both the head and trail
-- are variable size. Otherwise if headcnt or trailcnt is non-zero then
-- the machine recognizes a pattern with trailing context and headcnt is
-- the number of characters in the matched part of the pattern, or zero
-- if the matched part has variable length. trailcnt is the number of
-- trailing context characters in the pattern, or zero if the trailing
-- context has variable length.
procedure FINISH_RULE(MACH : in INTEGER;
VARIABLE_TRAIL_RULE : in BOOLEAN;
HEADCNT, TRAILCNT : in INTEGER) is
P_MACH : INTEGER;
use TEXT_IO;
begin
P_MACH := MACH;
ADD_ACCEPT(P_MACH, NUM_RULES);
-- we did this in new_rule(), but it often gets the wrong
-- number because we do it before we start parsing the current rule
RULE_LINENUM(NUM_RULES) := LINENUM;
TEXT_IO.PUT(TEMP_ACTION_FILE, "when ");
INT_IO.PUT(TEMP_ACTION_FILE, NUM_RULES, 1);
TEXT_IO.PUT_LINE(TEMP_ACTION_FILE, " => ");
if (VARIABLE_TRAIL_RULE) then
RULE_TYPE(NUM_RULES) := RULE_VARIABLE;
if (PERFORMANCE_REPORT) then
TEXT_IO.PUT(STANDARD_ERROR, "Variable trailing context rule at line ");
INT_IO.PUT(STANDARD_ERROR, RULE_LINENUM(NUM_RULES), 1);
TEXT_IO.NEW_LINE(STANDARD_ERROR);
end if;
VARIABLE_TRAILING_CONTEXT_RULES := TRUE;
else
RULE_TYPE(NUM_RULES) := RULE_NORMAL;
if ((HEADCNT > 0) or (TRAILCNT > 0)) then
-- do trailing context magic to not match the trailing characters
TEXT_IO.PUT_LINE(TEMP_ACTION_FILE,
"yy_ch_buf(yy_cp) := yy_hold_char; -- undo effects of setting up yytext"
);
if (HEADCNT > 0) then
TEXT_IO.PUT(TEMP_ACTION_FILE, " yy_cp := yy_bp + ");
INT_IO.PUT(TEMP_ACTION_FILE, HEADCNT, 1);
TEXT_IO.PUT_LINE(TEMP_ACTION_FILE, ";");
else
TEXT_IO.PUT(TEMP_ACTION_FILE, "yy_cp := yy_cp - ");
INT_IO.PUT(TEMP_ACTION_FILE, TRAILCNT, 1);
TEXT_IO.PUT_LINE(TEMP_ACTION_FILE, ";");
end if;
TEXT_IO.PUT_LINE(TEMP_ACTION_FILE, "yy_c_buf_p := yy_cp;");
TEXT_IO.PUT_LINE(TEMP_ACTION_FILE,
"YY_DO_BEFORE_ACTION; -- set up yytext again");
end if;
end if;
MISC.LINE_DIRECTIVE_OUT(TEMP_ACTION_FILE);
end FINISH_RULE;
-- link_machines - connect two machines together
--
-- new - a machine constructed by connecting first to last
-- first - the machine whose successor is to be last
-- last - the machine whose predecessor is to be first
--
-- note: this routine concatenates the machine first with the machine
-- last to produce a machine new which will pattern-match first first
-- and then last, and will fail if either of the sub-patterns fails.
-- FIRST is set to new by the operation. last is unmolested.
function LINK_MACHINES(FIRST, LAST : in INTEGER) return INTEGER is
begin
if (FIRST = NIL) then
return LAST;
else
if (LAST = NIL) then
return FIRST;
else
MKXTION(FINALST(FIRST), LAST);
FINALST(FIRST) := FINALST(LAST);
LASTST(FIRST) := MAX(LASTST(FIRST), LASTST(LAST));
FIRSTST(FIRST) := MIN(FIRSTST(FIRST), FIRSTST(LAST));
return (FIRST);
end if;
end if;
end LINK_MACHINES;
-- mark_beginning_as_normal - mark each "beginning" state in a machine
-- as being a "normal" (i.e., not trailing context-
-- associated) states
--
-- The "beginning" states are the epsilon closure of the first state
procedure MARK_BEGINNING_AS_NORMAL(MACH : in INTEGER) is
begin
case (STATE_TYPE(MACH)) is
when STATE_NORMAL =>
-- oh, we've already visited here
return;
when STATE_TRAILING_CONTEXT =>
STATE_TYPE(MACH) := STATE_NORMAL;
if (TRANSCHAR(MACH) = SYM_EPSILON) then
if (TRANS1(MACH) /= NO_TRANSITION) then
MARK_BEGINNING_AS_NORMAL(TRANS1(MACH));
end if;
if (TRANS2(MACH) /= NO_TRANSITION) then
MARK_BEGINNING_AS_NORMAL(TRANS2(MACH));
end if;
end if;
when others =>
MISC.AFLEXERROR("bad state type in mark_beginning_as_normal()");
end case;
end MARK_BEGINNING_AS_NORMAL;
-- mkbranch - make a machine that branches to two machines
--
-- branch - a machine which matches either first's pattern or second's
-- first, second - machines whose patterns are to be or'ed (the | operator)
--
-- note that first and second are NEITHER destroyed by the operation. Also,
-- the resulting machine CANNOT be used with any other "mk" operation except
-- more mkbranch's. Compare with mkor()
function MKBRANCH(FIRST, SECOND : in INTEGER) return INTEGER is
EPS : INTEGER;
begin
if (FIRST = NO_TRANSITION) then
return SECOND;
else
if (SECOND = NO_TRANSITION) then
return FIRST;
end if;
end if;
EPS := MKSTATE(SYM_EPSILON);
MKXTION(EPS, FIRST);
MKXTION(EPS, SECOND);
return EPS;
end MKBRANCH;
-- mkclos - convert a machine into a closure
--
-- new - a new state which matches the closure of "state"
function MKCLOS(STATE : in INTEGER) return INTEGER is
begin
return NFA.MKOPT(MKPOSCL(STATE));
end MKCLOS;
-- mkopt - make a machine optional
--
-- new - a machine which optionally matches whatever mach matched
-- mach - the machine to make optional
--
-- notes:
-- 1. mach must be the last machine created
-- 2. mach is destroyed by the call
function MKOPT(MACH : in INTEGER) return INTEGER is
EPS : INTEGER;
RESULT : INTEGER;
begin
RESULT := MACH;
if (not SUPER_FREE_EPSILON(FINALST(RESULT))) then
EPS := NFA.MKSTATE(SYM_EPSILON);
RESULT := NFA.LINK_MACHINES(RESULT, EPS);
end if;
-- can't skimp on the following if FREE_EPSILON(mach) is true because
-- some state interior to "mach" might point back to the beginning
-- for a closure
EPS := NFA.MKSTATE(SYM_EPSILON);
RESULT := NFA.LINK_MACHINES(EPS, RESULT);
NFA.MKXTION(RESULT, FINALST(RESULT));
return RESULT;
end MKOPT;
-- mkor - make a machine that matches either one of two machines
--
-- new - a machine which matches either first's pattern or second's
-- first, second - machines whose patterns are to be or'ed (the | operator)
--
-- note that first and second are both destroyed by the operation
-- the code is rather convoluted because an attempt is made to minimize
-- the number of epsilon states needed
function MKOR(FIRST, SECOND : in INTEGER) return INTEGER is
EPS, OREND : INTEGER;
P_FIRST : INTEGER;
begin
P_FIRST := FIRST;
if (P_FIRST = NIL) then
return SECOND;
else
if (SECOND = NIL) then
return P_FIRST;
else
-- see comment in mkopt() about why we can't use the first state
-- of "first" or "second" if they satisfy "FREE_EPSILON"
EPS := MKSTATE(SYM_EPSILON);
P_FIRST := LINK_MACHINES(EPS, P_FIRST);
MKXTION(P_FIRST, SECOND);
if ((SUPER_FREE_EPSILON(FINALST(P_FIRST))) and (ACCPTNUM(FINALST(P_FIRST
)) = NIL)) then
OREND := FINALST(P_FIRST);
MKXTION(FINALST(SECOND), OREND);
else
if ((SUPER_FREE_EPSILON(FINALST(SECOND))) and (ACCPTNUM(FINALST(SECOND
)) = NIL)) then
OREND := FINALST(SECOND);
MKXTION(FINALST(P_FIRST), OREND);
else
EPS := MKSTATE(SYM_EPSILON);
P_FIRST := LINK_MACHINES(P_FIRST, EPS);
OREND := FINALST(P_FIRST);
MKXTION(FINALST(SECOND), OREND);
end if;
end if;
end if;
end if;
FINALST(P_FIRST) := OREND;
return P_FIRST;
end MKOR;
-- mkposcl - convert a machine into a positive closure
--
-- new - a machine matching the positive closure of "state"
function MKPOSCL(STATE : in INTEGER) return INTEGER is
EPS : INTEGER;
begin
if (SUPER_FREE_EPSILON(FINALST(STATE))) then
MKXTION(FINALST(STATE), STATE);
return (STATE);
else
EPS := MKSTATE(SYM_EPSILON);
MKXTION(EPS, STATE);
return (LINK_MACHINES(STATE, EPS));
end if;
end MKPOSCL;
-- mkrep - make a replicated machine
--
-- new - a machine that matches whatever "mach" matched from "lb"
-- number of times to "ub" number of times
--
-- note
-- if "ub" is INFINITY then "new" matches "lb" or more occurrences of "mach"
function MKREP(MACH, LB, UB : in INTEGER) return INTEGER is
BASE_MACH, TAIL, COPY : INTEGER;
P_MACH : INTEGER;
begin
P_MACH := MACH;
BASE_MACH := COPYSINGL(P_MACH, LB - 1);
if (UB = INFINITY) then
COPY := DUPMACHINE(P_MACH);
P_MACH := LINK_MACHINES(P_MACH, LINK_MACHINES(BASE_MACH, MKCLOS(COPY)));
else
TAIL := MKSTATE(SYM_EPSILON);
for I in LB .. UB - 1 loop
COPY := DUPMACHINE(P_MACH);
TAIL := MKOPT(LINK_MACHINES(COPY, TAIL));
end loop;
P_MACH := LINK_MACHINES(P_MACH, LINK_MACHINES(BASE_MACH, TAIL));
end if;
return P_MACH;
end MKREP;
-- mkstate - create a state with a transition on a given symbol
--
-- state - a new state matching sym
-- sym - the symbol the new state is to have an out-transition on
--
-- note that this routine makes new states in ascending order through the
-- state array (and increments LASTNFA accordingly). The routine DUPMACHINE
-- relies on machines being made in ascending order and that they are
-- CONTIGUOUS. Change it and you will have to rewrite DUPMACHINE (kludge
-- that it admittedly is)
function MKSTATE(SYM : in INTEGER) return INTEGER is
begin
LASTNFA := LASTNFA + 1;
if (LASTNFA >= CURRENT_MNS) then
CURRENT_MNS := CURRENT_MNS + MNS_INCREMENT;
if (CURRENT_MNS >= MAXIMUM_MNS) then
MISC.AFLEXERROR("input rules are too complicated (>= " & INTEGER'IMAGE(
CURRENT_MNS) & " NFA states) )");
end if;
NUM_REALLOCS := NUM_REALLOCS + 1;
REALLOCATE_INTEGER_ARRAY(FIRSTST, CURRENT_MNS);
REALLOCATE_INTEGER_ARRAY(LASTST, CURRENT_MNS);
REALLOCATE_INTEGER_ARRAY(FINALST, CURRENT_MNS);
REALLOCATE_INTEGER_ARRAY(TRANSCHAR, CURRENT_MNS);
REALLOCATE_INTEGER_ARRAY(TRANS1, CURRENT_MNS);
REALLOCATE_INTEGER_ARRAY(TRANS2, CURRENT_MNS);
REALLOCATE_INTEGER_ARRAY(ACCPTNUM, CURRENT_MNS);
REALLOCATE_INTEGER_ARRAY(ASSOC_RULE, CURRENT_MNS);
REALLOCATE_STATE_ENUM_ARRAY(STATE_TYPE, CURRENT_MNS);
end if;
FIRSTST(LASTNFA) := LASTNFA;
FINALST(LASTNFA) := LASTNFA;
LASTST(LASTNFA) := LASTNFA;
TRANSCHAR(LASTNFA) := SYM;
TRANS1(LASTNFA) := NO_TRANSITION;
TRANS2(LASTNFA) := NO_TRANSITION;
ACCPTNUM(LASTNFA) := NIL;
ASSOC_RULE(LASTNFA) := NUM_RULES;
STATE_TYPE(LASTNFA) := CURRENT_STATE_ENUM;
-- fix up equivalence classes base on this transition. Note that any
-- character which has its own transition gets its own equivalence class.
-- Thus only characters which are only in character classes have a chance
-- at being in the same equivalence class. E.g. "a|b" puts 'a' and 'b'
-- into two different equivalence classes. "[ab]" puts them in the same
-- equivalence class (barring other differences elsewhere in the input).
if (SYM < 0) then
-- we don't have to update the equivalence classes since that was
-- already done when the ccl was created for the first time
null;
else
if (SYM = SYM_EPSILON) then
NUMEPS := NUMEPS + 1;
else
if (USEECS) then
ECS.MKECHAR(SYM, NEXTECM, ECGROUP);
end if;
end if;
end if;
return LASTNFA;
end MKSTATE;
-- mkxtion - make a transition from one state to another
--
-- statefrom - the state from which the transition is to be made
-- stateto - the state to which the transition is to be made
procedure MKXTION(STATEFROM, STATETO : in INTEGER) is
begin
if (TRANS1(STATEFROM) = NO_TRANSITION) then
TRANS1(STATEFROM) := STATETO;
else
if ((TRANSCHAR(STATEFROM) /= SYM_EPSILON) or (TRANS2(STATEFROM) /=
NO_TRANSITION)) then
MISC.AFLEXFATAL("found too many transitions in mkxtion()");
else
-- second out-transition for an epsilon state
EPS2 := EPS2 + 1;
TRANS2(STATEFROM) := STATETO;
end if;
end if;
end MKXTION;
-- new_rule - initialize for a new rule
--
-- the global num_rules is incremented and the any corresponding dynamic
-- arrays (such as rule_type()) are grown as needed.
procedure NEW_RULE is
begin
NUM_RULES := NUM_RULES + 1;
if (NUM_RULES >= CURRENT_MAX_RULES) then
NUM_REALLOCS := NUM_REALLOCS + 1;
CURRENT_MAX_RULES := CURRENT_MAX_RULES + MAX_RULES_INCREMENT;
REALLOCATE_RULE_ENUM_ARRAY(RULE_TYPE, CURRENT_MAX_RULES);
REALLOCATE_INTEGER_ARRAY(RULE_LINENUM, CURRENT_MAX_RULES);
end if;
if (NUM_RULES > MAX_RULE) then
MISC.AFLEXERROR("too many rules (> " & INTEGER'IMAGE(MAX_RULE) & ")!");
end if;
RULE_LINENUM(NUM_RULES) := LINENUM;
end NEW_RULE;
end NFA;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE NFA construction routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION builds the NFA.
-- NOTES this file mirrors flex as closely as possible.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/nfaS.a,v 1.4 90/01/12 15:20:30 self Exp Locker: self $
package NFA is
procedure ADD_ACCEPT(MACH : in out INTEGER;
ACCEPTING_NUMBER : in INTEGER);
function COPYSINGL(SINGL, NUM : in INTEGER) return INTEGER;
procedure DUMPNFA(STATE1 : in INTEGER);
function DUPMACHINE(MACH : in INTEGER) return INTEGER;
procedure FINISH_RULE(MACH : in INTEGER;
VARIABLE_TRAIL_RULE : in BOOLEAN;
HEADCNT, TRAILCNT : in INTEGER);
function LINK_MACHINES(FIRST, LAST : in INTEGER) return INTEGER;
procedure MARK_BEGINNING_AS_NORMAL(MACH : in INTEGER);
function MKBRANCH(FIRST, SECOND : in INTEGER) return INTEGER;
function MKCLOS(STATE : in INTEGER) return INTEGER;
function MKOPT(MACH : in INTEGER) return INTEGER;
function MKOR(FIRST, SECOND : in INTEGER) return INTEGER;
function MKPOSCL(STATE : in INTEGER) return INTEGER;
function MKREP(MACH, LB, UB : in INTEGER) return INTEGER;
function MKSTATE(SYM : in INTEGER) return INTEGER;
procedure MKXTION(STATEFROM, STATETO : in INTEGER);
procedure NEW_RULE;
end NFA;
with Parse_Tokens, Parse_Goto, Parse_Shift_Reduce, Text_IO, scanner;
with NFA, ccl, misc, misc_defs, sym, ecs, aflex_scanner;
with tstring, int_io, main_body, text_io, external_file_manager;
use aflex_scanner, external_file_manager;
package parser is
procedure build_eof_action;
procedure yyerror(msg: string);
procedure YYParse;
def_rule:integer;
end parser;
package body parser is
-- build_eof_action - build the "<<EOF>>" action for the active start
-- conditions
use text_io, misc_defs;
procedure build_eof_action is
begin
text_io.put( temp_action_file, "when " );
for i in 1..actvp loop
if ( sceof(actvsc(i)) ) then
text_io.put( Standard_Error,
"multiple <<EOF>> rules for start condition ");
tstring.put( Standard_Error, scname(actvsc(i)));
main_body.aflexend(1);
else
sceof(actvsc(i)) := true;
text_io.put( temp_action_file, "YY_END_OF_BUFFER +" );
tstring.put( temp_action_file, scname(actvsc(i)) );
text_io.put_line( temp_action_file, " + 1 " );
if (i /= actvp) then
text_io.put_line( temp_action_file, " |" );
else
text_io.put_line( temp_action_file, " =>" );
end if;
end if;
end loop;
misc.line_directive_out( temp_action_file );
end build_eof_action;
-- yyerror - eat up an error message from the parser
--
-- synopsis
-- char msg[];
-- yyerror( msg );
procedure yyerror( msg : string ) is
begin
null;
end yyerror;
use Parse_Goto, Parse_Shift_Reduce, Text_IO, misc_defs, tstring;
procedure YYParse is
-- Rename User Defined Packages to Internal Names.
package yy_goto_tables renames
Parse_Goto;
package yy_shift_reduce_tables renames
Parse_Shift_Reduce;
package yy_tokens renames
Parse_Tokens;
use yy_tokens, yy_goto_tables, yy_shift_reduce_tables;
procedure yyerrok;
procedure yyclearin;
package yy is
-- the size of the value and state stacks
stack_size : constant Natural := 300;
-- subtype rule is natural;
subtype parse_state is natural;
-- subtype nonterminal is integer;
-- encryption constants
default : constant := -1;
first_shift_entry : constant := 0;
accept_code : constant := -1001;
error_code : constant := -1000;
-- stack data used by the parser
tos : natural := 0;
value_stack : array(0..stack_size) of yy_tokens.yystype;
state_stack : array(0..stack_size) of parse_state;
-- current input symbol and action the parser is on
action : integer;
rule_id : rule;
input_symbol : yy_tokens.token;
-- error recovery flag
error_flag : natural := 0;
-- indicates 3 - (number of valid shifts after an error occurs)
look_ahead : boolean := true;
index : integer;
-- Is Debugging option on or off
DEBUG : constant boolean := FALSE;
end yy;
function goto_state
(state : yy.parse_state;
sym : nonterminal) return yy.parse_state;
function parse_action
(state : yy.parse_state;
t : yy_tokens.token) return integer;
pragma inline(goto_state, parse_action);
function goto_state(state : yy.parse_state;
sym : nonterminal) return yy.parse_state is
index : integer;
begin
index := goto_offset(state);
while integer(goto_matrix(index).nonterm) /= sym loop
index := index + 1;
end loop;
return integer(goto_matrix(index).newstate);
end goto_state;
function parse_action(state : yy.parse_state;
t : yy_tokens.token) return integer is
index : integer;
tok_pos : integer;
default : constant integer := -1;
begin
tok_pos := yy_tokens.token'pos(t);
index := shift_reduce_offset(state);
while integer(shift_reduce_matrix(index).t) /= tok_pos and then
integer(shift_reduce_matrix(index).t) /= default
loop
index := index + 1;
end loop;
return integer(shift_reduce_matrix(index).act);
end parse_action;
-- error recovery stuff
procedure handle_error is
temp_action : integer;
begin
if yy.error_flag = 3 then -- no shift yet, clobber input.
if yy.debug then
put_line("Ayacc.YYParse: Error Recovery Clobbers " &
yy_tokens.token'image(yy.input_symbol));
end if;
if yy.input_symbol = yy_tokens.end_of_input then -- don't discard,
if yy.debug then
put_line("Ayacc.YYParse: Can't discard END_OF_INPUT, quiting...");
end if;
raise yy_tokens.syntax_error;
end if;
yy.look_ahead := true; -- get next token
return; -- and try again...
end if;
if yy.error_flag = 0 then -- brand new error
yyerror("Syntax Error");
end if;
yy.error_flag := 3;
-- find state on stack where error is a valid shift --
if yy.debug then
put_line("Ayacc.YYParse: Looking for state with error as valid shift");
end if;
loop
if yy.debug then
put_line("Ayacc.YYParse: Examining State " &
yy.parse_state'image(yy.state_stack(yy.tos)));
end if;
temp_action := parse_action(yy.state_stack(yy.tos), error);
if temp_action >= yy.first_shift_entry then
yy.tos := yy.tos + 1;
yy.state_stack(yy.tos) := temp_action;
exit;
end if;
Decrement_Stack_Pointer :
begin
yy.tos := yy.tos - 1;
exception
when Constraint_Error =>
yy.tos := 0;
end Decrement_Stack_Pointer;
if yy.tos = 0 then
if yy.debug then
put_line("Ayacc.YYParse: Error recovery popped entire stack, aborting...");
end if;
raise yy_tokens.syntax_error;
end if;
end loop;
if yy.debug then
put_line("Ayacc.YYParse: Shifted error token in state " &
yy.parse_state'image(yy.state_stack(yy.tos)));
end if;
end handle_error;
-- print debugging information for a shift operation
procedure shift_debug(state_id: yy.parse_state; lexeme: yy_tokens.token) is
begin
put_line("Ayacc.YYParse: Shift "& yy.parse_state'image(state_id)&" on input symbol "&
yy_tokens.token'image(lexeme) );
end;
-- print debugging information for a reduce operation
procedure reduce_debug(rule_id: rule; state_id: yy.parse_state) is
begin
put_line("Ayacc.YYParse: Reduce by rule "&rule'image(rule_id)&" goto state "&
yy.parse_state'image(state_id));
end;
-- make the parser believe that 3 valid shifts have occured.
-- used for error recovery.
procedure yyerrok is
begin
yy.error_flag := 0;
end yyerrok;
-- called to clear input symbol that caused an error.
procedure yyclearin is
begin
-- yy.input_symbol := yylex;
yy.look_ahead := true;
end yyclearin;
begin
-- initialize by pushing state 0 and getting the first input symbol
yy.state_stack(yy.tos) := 0;
loop
yy.index := shift_reduce_offset(yy.state_stack(yy.tos));
if integer(shift_reduce_matrix(yy.index).t) = yy.default then
yy.action := integer(shift_reduce_matrix(yy.index).act);
else
if yy.look_ahead then
yy.look_ahead := false;
yy.input_symbol := yylex;
end if;
yy.action :=
parse_action(yy.state_stack(yy.tos), yy.input_symbol);
end if;
if yy.action >= yy.first_shift_entry then -- SHIFT
if yy.debug then
shift_debug(yy.action, yy.input_symbol);
end if;
-- Enter new state
yy.tos := yy.tos + 1;
yy.state_stack(yy.tos) := yy.action;
yy.value_stack(yy.tos) := yylval;
if yy.error_flag > 0 then -- indicate a valid shift
yy.error_flag := yy.error_flag - 1;
end if;
-- Advance lookahead
yy.look_ahead := true;
elsif yy.action = yy.error_code then -- ERROR
handle_error;
elsif yy.action = yy.accept_code then
if yy.debug then
put_line("Ayacc.YYParse: Accepting Grammar...");
end if;
exit;
else -- Reduce Action
-- Convert action into a rule
yy.rule_id := -1 * yy.action;
-- Execute User Action
-- user_action(yy.rule_id);
case yy.rule_id is
when 1 =>
--#line 44
-- add default rule
pat := ccl.cclinit;
ccl.cclnegate( pat );
def_rule := nfa.mkstate( -pat );
nfa.finish_rule( def_rule, false, 0, 0 );
for i in 1 .. lastsc loop
scset(i) := nfa.mkbranch( scset(i), def_rule );
end loop;
if ( spprdflt ) then
text_io.put(temp_action_file,
"raise AFLEX_SCANNER_JAMMED;");
else
text_io.put( temp_action_file, "ECHO" );
text_io.put_line( temp_action_file, ";" );
end if;
when 2 =>
--#line 69
-- initialize for processing rules
-- create default DFA start condition
sym.scinstal( tstring.vstr("INITIAL"), false );
when 5 =>
--#line 80
misc.synerr( "unknown error processing section 1" );
when 7 =>
--#line 87
-- these productions are separate from the s1object
-- rule because the semantics must be done before
-- we parse the remainder of an s1object
xcluflg := false;
when 8 =>
--#line 97
xcluflg := true;
when 9 =>
--#line 101
sym.scinstal( nmstr, xcluflg );
when 10 =>
--#line 104
sym.scinstal( nmstr, xcluflg );
when 11 =>
--#line 107
misc.synerr( "bad start condition list" );
when 14 =>
--#line 115
-- initialize for a parse of one rule
trlcontxt := false;
variable_trail_rule := false;
varlength := false;
trailcnt := 0;
headcnt := 0;
rulelen := 0;
current_state_enum := STATE_NORMAL;
previous_continued_action := continued_action;
nfa.new_rule;
when 15 =>
--#line 130
pat := nfa.link_machines(
yy.value_stack(yy.tos-1),
yy.value_stack(yy.tos) );
nfa.finish_rule( pat, variable_trail_rule,
headcnt, trailcnt );
for i in 1 .. actvp loop
scbol(actvsc(i)) :=
nfa.mkbranch( scbol(actvsc(i)), pat );
end loop;
if ( not bol_needed ) then
bol_needed := true;
if ( performance_report ) then
text_io.put( Standard_Error,
"'^' operator results in sub-optimal performance");
text_io.new_line(Standard_Error);
end if;
end if;
when 16 =>
--#line 152
pat := nfa.link_machines(
yy.value_stack(yy.tos-1),
yy.value_stack(yy.tos) );
nfa.finish_rule( pat, variable_trail_rule,
headcnt, trailcnt );
for i in 1 .. actvp loop
scset(actvsc(i)) :=
nfa.mkbranch( scset(actvsc(i)), pat );
end loop;
when 17 =>
--#line 163
pat := nfa.link_machines(
yy.value_stack(yy.tos-1),
yy.value_stack(yy.tos) );
nfa.finish_rule( pat, variable_trail_rule,
headcnt, trailcnt );
-- add to all non-exclusive start conditions,
-- including the default (0) start condition
for i in 1 .. lastsc loop
if ( not scxclu(i) ) then
scbol(i) := nfa.mkbranch( scbol(i), pat );
end if;
end loop;
if ( not bol_needed ) then
bol_needed := true;
if ( performance_report ) then
text_io.put( Standard_Error,
"'^' operator results in sub-optimal performance");
text_io.new_line(Standard_Error);
end if;
end if;
when 18 =>
--#line 188
pat := nfa.link_machines(
yy.value_stack(yy.tos-1),
yy.value_stack(yy.tos) );
nfa.finish_rule( pat, variable_trail_rule,
headcnt, trailcnt );
for i in 1 .. lastsc loop
if ( not scxclu(i) ) then
scset(i) := nfa.mkbranch( scset(i), pat );
end if;
end loop;
when 19 =>
--#line 201
build_eof_action;
when 20 =>
--#line 204
-- this EOF applies only to the INITIAL start cond.
actvp := 1;
actvsc(actvp) := 1;
build_eof_action;
when 21 =>
--#line 212
misc.synerr( "unrecognized rule" );
when 23 =>
--#line 219
scnum := sym.sclookup( nmstr );
if (scnum = 0 ) then
text_io.put( Standard_Error,
"undeclared start condition ");
tstring.put( Standard_Error, nmstr );
main_body.aflexend( 1 );
else
actvp := actvp + 1;
actvsc(actvp) := scnum;
end if;
when 24 =>
--#line 233
scnum := sym.sclookup( nmstr );
if (scnum = 0 ) then
text_io.put( Standard_Error,
"undeclared start condition ");
tstring.put( Standard_Error, nmstr );
main_body.aflexend ( 1 );
else
actvp := 1;
actvsc(actvp) := scnum;
end if;
when 25 =>
--#line 247
misc.synerr( "bad start condition list" );
when 26 =>
--#line 251
if trlcontxt then
misc.synerr( "trailing context used twice" );
yyval := nfa.mkstate( SYM_EPSILON );
else
trlcontxt := true;
if ( not varlength ) then
headcnt := rulelen;
end if;
rulelen := rulelen + 1;
trailcnt := 1;
eps := nfa.mkstate( SYM_EPSILON );
yyval := nfa.link_machines( eps,
nfa.mkstate( CHARACTER'POS(ASCII.LF) ) );
end if;
when 27 =>
--#line 272
yyval := nfa.mkstate( SYM_EPSILON );
if ( trlcontxt ) then
if ( varlength and (headcnt = 0) ) then
-- both head and trail are variable-length
variable_trail_rule := true;
else
trailcnt := rulelen;
end if;
end if;
when 28 =>
--#line 287
varlength := true;
yyval := nfa.mkor(
yy.value_stack(yy.tos-2),
yy.value_stack(yy.tos) );
when 29 =>
--#line 294
if ( transchar(lastst(
yy.value_stack(yy.tos))) /= SYM_EPSILON ) then
-- provide final transition \now/ so it
-- will be marked as a trailing context
-- state
yy.value_stack(yy.tos) := nfa.link_machines(
yy.value_stack(yy.tos), nfa.mkstate( SYM_EPSILON ) );
end if;
nfa.mark_beginning_as_normal(
yy.value_stack(yy.tos) );
current_state_enum := STATE_NORMAL;
if ( previous_continued_action ) then
-- we need to treat this as variable trailing
-- context so that the backup does not happen
-- in the action but before the action switch
-- statement. If the backup happens in the
-- action, then the rules "falling into" this
-- one's action will *also* do the backup,
-- erroneously.
if ( (not varlength) or headcnt /= 0 ) then
text_io.put( Standard_Error,
"alex: warning - trailing context rule at line");
int_io.put(Standard_Error, linenum);
text_io.put( Standard_Error,
"made variable because of preceding '|' action" );
int_io.put(Standard_Error, linenum);
end if;
-- mark as variable
varlength := true;
headcnt := 0;
end if;
if ( varlength and (headcnt = 0) ) then
-- variable trailing context rule
-- mark the first part of the rule as the accepting
-- "head" part of a trailing context rule
-- by the way, we didn't do this at the beginning
-- of this production because back then
-- current_state_enum was set up for a trail
-- rule, and add_accept() can create a new
-- state ...
nfa.add_accept(
yy.value_stack(yy.tos-1),
misc.set_yy_trailing_head_mask(num_rules) );
end if;
yyval := nfa.link_machines(
yy.value_stack(yy.tos-1),
yy.value_stack(yy.tos) );
when 30 =>
--#line 348
yyval :=
yy.value_stack(yy.tos);
when 31 =>
--#line 353
-- this rule is separate from the others for "re" so
-- that the reduction will occur before the trailing
-- series is parsed
if ( trlcontxt ) then
misc.synerr( "trailing context used twice" );
else
trlcontxt := true;
end if;
if ( varlength ) then
-- we hope the trailing context is fixed-length
varlength := false;
else
headcnt := rulelen;
end if;
rulelen := 0;
current_state_enum := STATE_TRAILING_CONTEXT;
yyval :=
yy.value_stack(yy.tos-1);
when 32 =>
--#line 379
-- this is where concatenation of adjacent patterns
-- gets done
yyval := nfa.link_machines(
yy.value_stack(yy.tos-1),
yy.value_stack(yy.tos) );
when 33 =>
--#line 387
yyval :=
yy.value_stack(yy.tos);
when 34 =>
--#line 391
varlength := true;
yyval := nfa.mkclos(
yy.value_stack(yy.tos-1) );
when 35 =>
--#line 398
varlength := true;
yyval := nfa.mkposcl(
yy.value_stack(yy.tos-1) );
when 36 =>
--#line 405
varlength := true;
yyval := nfa.mkopt(
yy.value_stack(yy.tos-1) );
when 37 =>
--#line 412
varlength := true;
if ( (
yy.value_stack(yy.tos-3) >
yy.value_stack(yy.tos-1)) or (
yy.value_stack(yy.tos-3) < 0) ) then
misc.synerr( "bad iteration values" );
yyval :=
yy.value_stack(yy.tos-5);
else
if (
yy.value_stack(yy.tos-3) = 0 ) then
yyval := nfa.mkopt( nfa.mkrep(
yy.value_stack(yy.tos-5),
yy.value_stack(yy.tos-3),
yy.value_stack(yy.tos-1) ) );
else
yyval := nfa.mkrep(
yy.value_stack(yy.tos-5),
yy.value_stack(yy.tos-3),
yy.value_stack(yy.tos-1) );
end if;
end if;
when 38 =>
--#line 428
varlength := true;
if (
yy.value_stack(yy.tos-2) <= 0 ) then
misc.synerr( "iteration value must be positive" );
yyval :=
yy.value_stack(yy.tos-4);
else
yyval := nfa.mkrep(
yy.value_stack(yy.tos-4),
yy.value_stack(yy.tos-2), INFINITY );
end if;
when 39 =>
--#line 440
-- the singleton could be something like "(foo)",
-- in which case we have no idea what its length
-- is, so we punt here.
varlength := true;
if (
yy.value_stack(yy.tos-1) <= 0 ) then
misc.synerr( "iteration value must be positive" );
yyval :=
yy.value_stack(yy.tos-3);
else
yyval := nfa.link_machines(
yy.value_stack(yy.tos-3), nfa.copysingl(
yy.value_stack(yy.tos-3),
yy.value_stack(yy.tos-1) - 1 ) );
end if;
when 40 =>
--#line 456
if ( not madeany ) then
-- create the '.' character class
anyccl := ccl.cclinit;
ccl.ccladd( anyccl, ASCII.LF );
ccl.cclnegate( anyccl );
if ( useecs ) then
ecs.mkeccl(
ccltbl(cclmap(anyccl)..cclmap(anyccl) + ccllen(anyccl)),
ccllen(anyccl), nextecm,
ecgroup, CSIZE );
end if;
madeany := true;
end if;
rulelen := rulelen + 1;
yyval := nfa.mkstate( -anyccl );
when 41 =>
--#line 478
if ( not cclsorted ) then
-- sort characters for fast searching. We use a
-- shell sort since this list could be large.
-- misc.cshell( ccltbl + cclmap($1), ccllen($1) );
misc.cshell( ccltbl(cclmap(
yy.value_stack(yy.tos))..cclmap(
yy.value_stack(yy.tos)) + ccllen(
yy.value_stack(yy.tos))),
ccllen(
yy.value_stack(yy.tos)) );
end if;
if ( useecs ) then
ecs.mkeccl( ccltbl(cclmap(
yy.value_stack(yy.tos))..cclmap(
yy.value_stack(yy.tos)) + ccllen(
yy.value_stack(yy.tos))),
ccllen(
yy.value_stack(yy.tos)),nextecm, ecgroup, CSIZE );
end if;
rulelen := rulelen + 1;
yyval := nfa.mkstate( -
yy.value_stack(yy.tos) );
when 42 =>
--#line 499
rulelen := rulelen + 1;
yyval := nfa.mkstate( -
yy.value_stack(yy.tos) );
when 43 =>
--#line 506
yyval :=
yy.value_stack(yy.tos-1);
when 44 =>
--#line 509
yyval :=
yy.value_stack(yy.tos-1);
when 45 =>
--#line 512
rulelen := rulelen + 1;
if (
yy.value_stack(yy.tos) = CHARACTER'POS(ASCII.NUL) ) then
misc.synerr( "null in rule" );
end if;
if ( caseins and (
yy.value_stack(yy.tos) >= CHARACTER'POS('A')) and (
yy.value_stack(yy.tos) <= CHARACTER'POS('Z')) ) then
yy.value_stack(yy.tos) := misc.clower(
yy.value_stack(yy.tos) );
end if;
yyval := nfa.mkstate(
yy.value_stack(yy.tos) );
when 46 =>
--#line 528
yyval :=
yy.value_stack(yy.tos-1);
when 47 =>
--#line 531
-- *Sigh* - to be compatible Unix lex, negated ccls
-- match newlines
ccl.cclnegate(
yy.value_stack(yy.tos-1) );
yyval :=
yy.value_stack(yy.tos-1);
when 48 =>
--#line 540
if (
yy.value_stack(yy.tos-2) >
yy.value_stack(yy.tos) ) then
misc.synerr( "negative range in character class" );
else
if ( caseins ) then
if ( (
yy.value_stack(yy.tos-2) >= CHARACTER'POS('A')) and (
yy.value_stack(yy.tos-2) <= CHARACTER'POS('Z')) ) then
yy.value_stack(yy.tos-2) := misc.clower(
yy.value_stack(yy.tos-2) );
end if;
if ( (
yy.value_stack(yy.tos) >= CHARACTER'POS('A')) and (
yy.value_stack(yy.tos) <= CHARACTER'POS('Z')) ) then
yy.value_stack(yy.tos) := misc.clower(
yy.value_stack(yy.tos) );
end if;
end if;
for i in
yy.value_stack(yy.tos-2) ..
yy.value_stack(yy.tos) loop
ccl.ccladd(
yy.value_stack(yy.tos-3), CHARACTER'VAL(i) );
end loop;
-- keep track if this ccl is staying in
-- alphabetical order
cclsorted := cclsorted and (
yy.value_stack(yy.tos-2) > lastchar);
lastchar :=
yy.value_stack(yy.tos);
end if;
yyval :=
yy.value_stack(yy.tos-3);
when 49 =>
--#line 568
if ( caseins ) then
if ( (
yy.value_stack(yy.tos) >= CHARACTER'POS('A')) and (
yy.value_stack(yy.tos) <= CHARACTER'POS('Z')) ) then
yy.value_stack(yy.tos) := misc.clower(
yy.value_stack(yy.tos) );
end if;
end if;
ccl.ccladd(
yy.value_stack(yy.tos-1), CHARACTER'VAL(
yy.value_stack(yy.tos)) );
cclsorted := cclsorted and (
yy.value_stack(yy.tos) > lastchar);
lastchar :=
yy.value_stack(yy.tos);
yyval :=
yy.value_stack(yy.tos-1);
when 50 =>
--#line 581
cclsorted := true;
lastchar := 0;
yyval := ccl.cclinit;
when 51 =>
--#line 589
if ( caseins ) then
if ( (
yy.value_stack(yy.tos) >= CHARACTER'POS('A')) and (
yy.value_stack(yy.tos) <= CHARACTER'POS('Z')) ) then
yy.value_stack(yy.tos) := misc.clower(
yy.value_stack(yy.tos) );
end if;
end if;
rulelen := rulelen + 1;
yyval := nfa.link_machines(
yy.value_stack(yy.tos-1), nfa.mkstate(
yy.value_stack(yy.tos) ) );
when 52 =>
--#line 602
yyval := nfa.mkstate( SYM_EPSILON );
when others => null;
end case;
-- Pop RHS states and goto next state
yy.tos := yy.tos - rule_length(yy.rule_id) + 1;
yy.state_stack(yy.tos) := goto_state(yy.state_stack(yy.tos-1) ,
get_lhs_rule(yy.rule_id));
yy.value_stack(yy.tos) := yyval;
if yy.debug then
reduce_debug(yy.rule_id,
goto_state(yy.state_stack(yy.tos - 1),
get_lhs_rule(yy.rule_id)));
end if;
end if;
end loop;
end yyparse;
end parser;
package Parse_Goto is
type Small_Integer is range -32_000 .. 32_000;
type Goto_Entry is record
Nonterm : Small_Integer;
Newstate : Small_Integer;
end record;
--pragma suppress(index_check);
subtype Row is Integer range -1 .. Integer'Last;
type Goto_Parse_Table is array (Row range <>) of Goto_Entry;
Goto_Matrix : constant Goto_Parse_Table :=
((-1,-1) -- Dummy Entry.
-- State 0
,(-3, 1),(-2, 2)
-- State 1
,(-4, 3)
-- State 2
-- State 3
,(-8, 10)
,(-5, 9)
-- State 4
-- State 5
-- State 6
-- State 7
-- State 8
-- State 9
,(-6, 12)
-- State 10
-- State 11
-- State 12
,(-7, 14)
-- State 13
,(-9, 15)
-- State 14
,(-18, 28),(-17, 26),(-16, 24),(-15, 25)
,(-12, 20),(-11, 18),(-10, 34)
-- State 15
-- State 16
-- State 17
-- State 18
,(-18, 28)
,(-17, 26),(-16, 24),(-15, 25),(-12, 37)
-- State 19
,(-18, 28),(-17, 26),(-16, 24),(-15, 25)
,(-12, 40)
-- State 20
,(-13, 42)
-- State 21
-- State 22
-- State 23
,(-14, 45)
-- State 24
,(-18, 28)
,(-17, 26),(-15, 48)
-- State 25
,(-18, 28),(-17, 49)
-- State 26
-- State 27
-- State 28
-- State 29
-- State 30
,(-19, 54)
-- State 31
,(-18, 28),(-17, 26),(-16, 24)
,(-15, 25),(-12, 55)
-- State 32
-- State 33
,(-20, 56)
-- State 34
-- State 35
-- State 36
-- State 37
,(-13, 60)
-- State 38
,(-18, 28),(-17, 26),(-16, 24),(-15, 25)
,(-12, 61)
-- State 39
-- State 40
,(-13, 62)
-- State 41
-- State 42
-- State 43
,(-18, 28),(-17, 26)
,(-15, 63)
-- State 44
-- State 45
-- State 46
-- State 47
-- State 48
,(-18, 28),(-17, 49)
-- State 49
-- State 50
-- State 51
-- State 52
-- State 53
-- State 54
-- State 55
-- State 56
-- State 57
,(-20, 72)
-- State 58
-- State 59
-- State 60
-- State 61
,(-13, 73)
-- State 62
-- State 63
,(-18, 28),(-17, 49)
-- State 64
-- State 65
-- State 66
-- State 67
-- State 68
-- State 69
-- State 70
-- State 71
-- State 72
-- State 73
-- State 74
-- State 75
-- State 76
-- State 77
-- State 78
-- State 79
-- State 80
-- State 81
-- State 82
);
-- The offset vector
GOTO_OFFSET : array (0.. 82) of Integer :=
( 0,
2, 3, 3, 5, 5, 5, 5, 5, 5, 6,
6, 6, 7, 8, 15, 15, 15, 15, 20, 25,
26, 26, 26, 27, 30, 32, 32, 32, 32, 32,
33, 38, 38, 39, 39, 39, 39, 40, 45, 45,
46, 46, 46, 49, 49, 49, 49, 49, 51, 51,
51, 51, 51, 51, 51, 51, 51, 52, 52, 52,
52, 53, 53, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55);
subtype Rule is Natural;
subtype Nonterminal is Integer;
Rule_Length : array (Rule range 0 .. 52) of Natural := ( 2,
5, 0, 5, 0, 2, 1, 1, 1,
3, 1, 1, 4, 0, 0, 4, 3,
3, 2, 2, 1, 1, 3, 3, 1,
1, 1, 0, 3, 2, 1, 2, 2,
1, 2, 2, 2, 6, 5, 4, 1,
1, 1, 3, 3, 1, 3, 4, 4,
2, 0, 2, 0);
Get_LHS_Rule: array (Rule range 0 .. 52) of Nonterminal := (-1,
-2,-3,-4,-4,-4,-5,-8,-8,
-9,-9,-9,-6,-6,-7,-10,-10,
-10,-10,-10,-10,-10,-11,-14,-14,
-14,-13,-13,-12,-12,-12,-16,-15,
-15,-17,-17,-17,-17,-17,-17,-17,
-17,-17,-17,-17,-17,-18,-18,-20,
-20,-20,-19,-19);
end Parse_Goto;
package Parse_Shift_Reduce is
type Small_Integer is range -32_000 .. 32_000;
type Shift_Reduce_Entry is record
T : Small_Integer;
Act : Small_Integer;
end record;
pragma Pack(Shift_Reduce_Entry);
subtype Row is Integer range -1 .. Integer'Last;
--pragma suppress(index_check);
type Shift_Reduce_Array is array (Row range <>) of Shift_Reduce_Entry;
Shift_Reduce_Matrix : constant Shift_Reduce_Array :=
( (-1,-1) -- Dummy Entry
-- state 0
,(-1,-2)
-- state 1
,( 1, 4),(-1,-4)
-- state 2
,( 0,-1001)
,(-1,-1000)
-- state 3
,( 4, 6),( 5, 7),( 6, 8)
,(-1,-1000)
-- state 4
,( 11, 11),(-1,-1000)
-- state 5
,(-1,-1000)
-- state 6
,(-1,-6)
-- state 7
,(-1,-7)
-- state 8
,(-1,-8)
-- state 9
,(-1,-13)
-- state 10
,( 7, 13),(-1,-1000)
-- state 11
,(-1,-5)
-- state 12
,(-1,-14)
-- state 13
,( 1, 17),( 8, 16),(-1,-1000)
-- state 14
,( 1, 22)
,( 2, 32),( 9, 29),( 10, 21),( 12, 19)
,( 13, 23),( 24, 27),( 25, 30),( 26, 31)
,( 28, 33),(-1,-1)
-- state 15
,( 7, 36),( 11, 35)
,(-1,-1000)
-- state 16
,(-1,-10)
-- state 17
,(-1,-11)
-- state 18
,( 2, 32)
,( 9, 29),( 10, 39),( 12, 38),( 24, 27)
,( 25, 30),( 26, 31),( 28, 33),(-1,-1000)
-- state 19
,( 2, 32),( 9, 29),( 24, 27),( 25, 30)
,( 26, 31),( 28, 33),(-1,-1000)
-- state 20
,( 16, 41)
,( 17, 43),( 18, 44),(-1,-27)
-- state 21
,(-1,-20)
-- state 22
,(-1,-21)
-- state 23
,( 1, 47),( 8, 46),(-1,-1000)
-- state 24
,( 2, 32),( 9, 29),( 24, 27),( 25, 30)
,( 26, 31),( 28, 33),(-1,-1000)
-- state 25
,( 2, 32)
,( 9, 29),( 24, 27),( 25, 30),( 26, 31)
,( 28, 33),(-1,-30)
-- state 26
,( 19, 50),( 20, 51)
,( 21, 52),( 22, 53),(-1,-33)
-- state 27
,(-1,-40)
-- state 28
,(-1,-41)
-- state 29
,(-1,-42)
-- state 30
,(-1,-52)
-- state 31
,( 2, 32)
,( 9, 29),( 24, 27),( 25, 30),( 26, 31)
,( 28, 33),(-1,-1000)
-- state 32
,(-1,-45)
-- state 33
,( 12, 57)
,(-1,-50)
-- state 34
,( 11, 58),(-1,-1000)
-- state 35
,(-1,-3)
-- state 36
,( 8, 59),(-1,-1000)
-- state 37
,( 16, 41),( 17, 43)
,( 18, 44),(-1,-27)
-- state 38
,( 2, 32),( 9, 29)
,( 24, 27),( 25, 30),( 26, 31),( 28, 33)
,(-1,-1000)
-- state 39
,(-1,-19)
-- state 40
,( 16, 41),( 17, 43)
,( 18, 44),(-1,-27)
-- state 41
,(-1,-26)
-- state 42
,(-1,-18)
-- state 43
,( 2, 32),( 9, 29),( 24, 27),( 25, 30)
,( 26, 31),( 28, 33),(-1,-1000)
-- state 44
,(-1,-31)
-- state 45
,( 14, 64),( 15, 65),(-1,-1000)
-- state 46
,(-1,-24)
-- state 47
,(-1,-25)
-- state 48
,( 2, 32),( 9, 29),( 24, 27)
,( 25, 30),( 26, 31),( 28, 33),(-1,-29)
-- state 49
,( 19, 50),( 20, 51),( 21, 52),( 22, 53)
,(-1,-32)
-- state 50
,(-1,-34)
-- state 51
,(-1,-35)
-- state 52
,(-1,-36)
-- state 53
,( 3, 66),(-1,-1000)
-- state 54
,( 2, 68),( 25, 67)
,(-1,-1000)
-- state 55
,( 17, 43),( 18, 44),( 27, 69)
,(-1,-1000)
-- state 56
,( 2, 71),( 29, 70),(-1,-1000)
-- state 57
,(-1,-50)
-- state 58
,(-1,-12)
-- state 59
,(-1,-9)
-- state 60
,(-1,-16)
-- state 61
,( 16, 41),( 17, 43),( 18, 44),(-1,-27)
-- state 62
,(-1,-17)
-- state 63
,( 2, 32),( 9, 29),( 24, 27)
,( 25, 30),( 26, 31),( 28, 33),(-1,-28)
-- state 64
,(-1,-22)
-- state 65
,( 8, 74),(-1,-1000)
-- state 66
,( 15, 75)
,( 23, 76),(-1,-1000)
-- state 67
,(-1,-43)
-- state 68
,(-1,-51)
-- state 69
,(-1,-44)
-- state 70
,(-1,-46)
-- state 71
,( 30, 77),(-1,-49)
-- state 72
,( 2, 71),( 29, 78),(-1,-1000)
-- state 73
,(-1,-15)
-- state 74
,(-1,-23)
-- state 75
,( 3, 79),( 23, 80),(-1,-1000)
-- state 76
,(-1,-39)
-- state 77
,( 2, 81),(-1,-1000)
-- state 78
,(-1,-47)
-- state 79
,( 23, 82),(-1,-1000)
-- state 80
,(-1,-38)
-- state 81
,(-1,-48)
-- state 82
,(-1,-37)
);
-- The offset vector
SHIFT_REDUCE_OFFSET : array (0.. 82) of Integer :=
( 0,
1, 3, 5, 9, 11, 12, 13, 14, 15, 16,
18, 19, 20, 23, 34, 37, 38, 39, 48, 55,
59, 60, 61, 64, 71, 78, 83, 84, 85, 86,
87, 94, 95, 97, 99, 100, 102, 106, 113, 114,
118, 119, 120, 127, 128, 131, 132, 133, 140, 145,
146, 147, 148, 150, 153, 157, 160, 161, 162, 163,
164, 168, 169, 176, 177, 179, 182, 183, 184, 185,
186, 188, 191, 192, 193, 196, 197, 199, 200, 202,
203, 204);
end Parse_Shift_Reduce;
with Text_Io;
with Ccl;
with Nfa;
with Parse_Shift_Reduce;
with Parse_Goto;
with Misc_Defs;
use Misc_Defs;
with External_File_Manager;
use External_File_Manager;
package Parse_Tokens is
subtype YYSType is Integer;
YYLVal, YYVal : YYSType;
type Token is
(End_Of_Input, Error, Char, Number,
Sectend, Scdecl, Xscdecl,
Whitespace, Name, Prevccl,
Eof_Op, Newline, '^',
'<', '>', ',',
'$', '|', '/',
'*', '+', '?',
'{', '}', '.',
'"', '(', ')',
'[', ']', '-' );
Syntax_Error : exception;
end Parse_Tokens;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE skeleton manager
-- AUTHOR: John Self (UCI)
-- DESCRIPTION outputs skeleton sections when called by gen.
-- NOTES allows use of internal or external skeleton
-- $Header: /tmp_mnt/dc/uc/self/arcadia/aflex/ada/src/RCS/skeleton_managerB.a,v 1.18 1991/08/06 17:58:45 self Exp self $
with MISC_DEFS, TEXT_IO, FILE_STRING;
package body SKELETON_MANAGER is
use FILE_STRING; -- to save having to type FILE_STRING 177 times
USE_EXTERNAL_SKELETON : BOOLEAN := FALSE;
-- are we using an external skelfile?
CURRENT_LINE : INTEGER := 1;
type FILE_ARRAY is array(POSITIVE range <>) of FILE_STRING.VSTRING;
SKEL_TEMPLATE : FILE_ARRAY(1 .. 177) := (
-- START OF SKELETON
-- START OF S1
VSTR("-- A lexical scanner generated by aflex"),
VSTR("with text_io; use text_io;"),
VSTR("%% user's code up to the double pound goes right here"),
-- BEGIN S2
VSTR("function YYLex return Token is"),
VSTR("subtype short is integer range -32768..32767;"),
VSTR(" yy_act : integer;"),
VSTR(" yy_c : short;"),
VSTR(""),
VSTR("-- returned upon end-of-file"),
VSTR("YY_END_TOK : constant integer := 0;"),
VSTR("%% tables get generated here."),
-- BEGIN S3
VSTR(""),
VSTR("-- copy whatever the last rule matched to the standard output"),
VSTR(""),
VSTR("procedure ECHO is"),
VSTR("begin"),
VSTR(" text_io.put( yytext );"),
VSTR("end ECHO;"),
VSTR(""),
VSTR("-- enter a start condition."),
VSTR("-- Using procedure requires a () after the ENTER, but makes everything"),
VSTR("-- much neater."),
VSTR(""),
VSTR("procedure ENTER( state : integer ) is"),
VSTR("begin"),
VSTR(" yy_start := 1 + 2 * state;"),
VSTR("end ENTER;"),
VSTR(""),
VSTR("-- action number for EOF rule of a given start state"),
VSTR("function YY_STATE_EOF(state : integer) return integer is"),
VSTR("begin"),
VSTR(" return YY_END_OF_BUFFER + state + 1;"),
VSTR("end YY_STATE_EOF;"),
VSTR(""),
VSTR("-- return all but the first 'n' matched characters back to the input stream"),
VSTR("procedure yyless(n : integer) is"),
VSTR("begin"),
VSTR(" yy_ch_buf(yy_cp) := yy_hold_char; -- undo effects of setting up yytext"),
VSTR(" yy_cp := yy_bp + n;"),
VSTR(" yy_c_buf_p := yy_cp;"),
VSTR(" YY_DO_BEFORE_ACTION; -- set up yytext again"),
VSTR("end yyless;"),
VSTR(""),
VSTR("-- redefine this if you have something you want each time."),
VSTR("procedure YY_USER_ACTION is"),
VSTR("begin"),
VSTR(" null;"),
VSTR("end;"),
VSTR(""),
VSTR("-- yy_get_previous_state - get the state just before the EOB char was reached"),
VSTR(""),
VSTR("function yy_get_previous_state return yy_state_type is"),
VSTR(" yy_current_state : yy_state_type;"),
VSTR(" yy_c : short;"),
VSTR("%% a local declaration of yy_bp goes here if bol_needed"),
VSTR("begin"),
VSTR("%% code to get the start state into yy_current_state goes here"),
-- BEGIN S3A
VSTR(""),
VSTR(" for yy_cp in yytext_ptr..yy_c_buf_p - 1 loop"),
VSTR("%% code to find the next state goes here"),
-- BEGIN S4
VSTR(" end loop;"),
VSTR(""),
VSTR(" return yy_current_state;"),
VSTR("end yy_get_previous_state;"),
VSTR(""),
VSTR("procedure yyrestart( input_file : file_type ) is"),
VSTR("begin"),
VSTR(" set_input(input_file);"),
VSTR(" yy_init := true;"),
VSTR("end yyrestart;"),
VSTR(""),
VSTR("begin -- of YYLex"),
VSTR("<<new_file>>"),
VSTR(" -- this is where we enter upon encountering an end-of-file and"),
VSTR(" -- yywrap() indicating that we should continue processing"),
VSTR(""),
VSTR(" if ( yy_init ) then"),
VSTR(" if ( yy_start = 0 ) then"),
VSTR(" yy_start := 1; -- first start state"),
VSTR(" end if;"),
VSTR(""),
VSTR(" -- we put in the '\n' and start reading from [1] so that an"),
VSTR(" -- initial match-at-newline will be true."),
VSTR(""),
VSTR(" yy_ch_buf(0) := ASCII.LF;"),
VSTR(" yy_n_chars := 1;"),
VSTR(""),
VSTR(" -- we always need two end-of-buffer characters. The first causes"),
VSTR(" -- a transition to the end-of-buffer state. The second causes"),
VSTR(" -- a jam in that state."),
VSTR(""),
VSTR(" yy_ch_buf(yy_n_chars) := YY_END_OF_BUFFER_CHAR;"),
VSTR(" yy_ch_buf(yy_n_chars + 1) := YY_END_OF_BUFFER_CHAR;"),
VSTR(""),
VSTR(" yy_eof_has_been_seen := false;"),
VSTR(""),
VSTR(" yytext_ptr := 1;"),
VSTR(" yy_c_buf_p := yytext_ptr;"),
VSTR(" yy_hold_char := yy_ch_buf(yy_c_buf_p);"),
VSTR(" yy_init := false;"),
VSTR(" end if; -- yy_init"),
VSTR(""),
VSTR(" loop -- loops until end-of-file is reached"),
VSTR(" yy_cp := yy_c_buf_p;"),
VSTR(""),
VSTR(" -- support of yytext"),
VSTR(" yy_ch_buf(yy_cp) := yy_hold_char;"),
VSTR(""),
VSTR(" -- yy_bp points to the position in yy_ch_buf of the start of the"),
VSTR(" -- current run."),
VSTR("%%"),
-- BEGIN S5
VSTR(""),
VSTR("<<next_action>>"),
VSTR("%% call to gen_find_action goes here"),
-- BEGIN S6
VSTR(" YY_DO_BEFORE_ACTION;"),
VSTR(" YY_USER_ACTION;"),
VSTR(""),
VSTR(" if aflex_debug then -- output acceptance info. for (-d) debug mode"),
VSTR(" text_io.put( Standard_Error, ""--accepting rule #"" );"),
VSTR(" text_io.put( Standard_Error, INTEGER'IMAGE(yy_act) );"),
VSTR(" text_io.put_line( Standard_Error, ""("""""" & yytext & """""")"");"),
VSTR(" end if;"),
VSTR(""),
VSTR("<<do_action>> -- this label is used only to access EOF actions"),
VSTR(" case yy_act is"), VSTR("%% actions go here"),
-- BEGIN S7
VSTR(" when YY_END_OF_BUFFER =>"),
VSTR(" -- undo the effects of YY_DO_BEFORE_ACTION"),
VSTR(" yy_ch_buf(yy_cp) := yy_hold_char;"),
VSTR(""),
VSTR(" yytext_ptr := yy_bp;"), VSTR(""),
VSTR(" case yy_get_next_buffer is"),
VSTR(" when EOB_ACT_END_OF_FILE =>"),
VSTR(" begin"),
VSTR(" if ( yywrap ) then"),
VSTR(" -- note: because we've taken care in"),
VSTR(" -- yy_get_next_buffer() to have set up yytext,"),
VSTR(" -- we can now set up yy_c_buf_p so that if some"),
VSTR(" -- total hoser (like aflex itself) wants"),
VSTR(" -- to call the scanner after we return the"),
VSTR(" -- End_Of_Input, it'll still work - another"),
VSTR(" -- End_Of_Input will get returned."),
VSTR(""),
VSTR(" yy_c_buf_p := yytext_ptr;"),
VSTR(""),
VSTR(" yy_act := YY_STATE_EOF((yy_start - 1) / 2);"),
VSTR(""),
VSTR(" goto do_action;"),
VSTR(" else"),
VSTR(" -- start processing a new file"),
VSTR(" yy_init := true;"),
VSTR(" goto new_file;"),
VSTR(" end if;"),
VSTR(" end;"),
VSTR(" when EOB_ACT_RESTART_SCAN =>"),
VSTR(" yy_c_buf_p := yytext_ptr;"),
VSTR(" yy_hold_char := yy_ch_buf(yy_c_buf_p);"),
VSTR(" when EOB_ACT_LAST_MATCH =>"),
VSTR(" yy_c_buf_p := yy_n_chars;"),
VSTR(" yy_current_state := yy_get_previous_state;"),
VSTR(""),
VSTR(" yy_cp := yy_c_buf_p;"),
VSTR(" yy_bp := yytext_ptr;"),
VSTR(" goto next_action;"),
VSTR(" when others => null;"),
VSTR(" end case; -- case yy_get_next_buffer()"),
VSTR(" when others =>"),
VSTR(" text_io.put( ""action # "" );"),
VSTR(" text_io.put( INTEGER'IMAGE(yy_act) );"),
VSTR(" text_io.new_line;"),
VSTR(" raise AFLEX_INTERNAL_ERROR;"),
VSTR(" end case; -- case (yy_act)"),
VSTR(" end loop; -- end of loop waiting for end of file"),
VSTR("end YYLex;"),
VSTR("%%"),
VSTR("ERROR tried to output beyond end of skeleton file")
-- END OF SKELETON
);
-- set_external_skeleton
--
-- DESCRIPTION
-- sets flag so we know to use an external skelfile
procedure SET_EXTERNAL_SKELETON is
begin
USE_EXTERNAL_SKELETON := TRUE;
end SET_EXTERNAL_SKELETON;
procedure GET_INTERNAL(BUFFER : in out FILE_STRING.VSTRING) is
begin
BUFFER := SKEL_TEMPLATE(CURRENT_LINE);
CURRENT_LINE := CURRENT_LINE + 1;
end GET_INTERNAL;
procedure GET_EXTERNAL(BUFFER : in out FILE_STRING.VSTRING) is
begin
FILE_STRING.GET_LINE(MISC_DEFS.SKELFILE, BUFFER);
end GET_EXTERNAL;
-- end_of_skeleton
--
-- DESCRIPTION
-- returns true if there are no more lines left to output in the skeleton
function END_OF_SKELETON return BOOLEAN is
begin
if (USE_EXTERNAL_SKELETON) then
-- we're using an external skelfile
return TEXT_IO.END_OF_FILE(MISC_DEFS.SKELFILE);
else
-- internal skeleton
return CURRENT_LINE > SKEL_TEMPLATE'LAST;
end if;
end END_OF_SKELETON;
procedure GET_FILE_LINE(BUFFER : in out FILE_STRING.VSTRING) is
begin
if (USE_EXTERNAL_SKELETON) then
GET_EXTERNAL(BUFFER);
else
GET_INTERNAL(BUFFER);
end if;
end GET_FILE_LINE;
-- skelout - write out one section of the skeleton file
--
-- DESCRIPTION
-- Either outputs internal skeleton, or from a file with "%%" dividers
-- if a skeleton file is specified by the user.
-- Copies from skelfile to stdout until a line beginning with "%%" or
-- EOF is found.
procedure SKELOUT is
BUF : FILE_STRING.VSTRING;
LINE_LEN : INTEGER;
begin
while (not END_OF_SKELETON) loop
GET_FILE_LINE(BUF);
if ((FILE_STRING.LEN(BUF) >= 2)
and then ((FILE_STRING.CHAR(BUF, 1) = '%')
and (FILE_STRING.CHAR(BUF, 2) = '%'))) then
exit;
else
FILE_STRING.PUT_LINE(BUF);
end if;
end loop;
end SKELOUT;
end SKELETON_MANAGER;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE skeleton manager
-- AUTHOR: John Self (UCI)
-- DESCRIPTION outputs skeleton sections when called by gen.
-- NOTES allows use of internal or external skeleton
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/skeleton_managerS.a,v 1.3 90/01/12 15:20:38 self Exp Locker: self $
with TSTRING; use TSTRING;
package SKELETON_MANAGER is
procedure SKELOUT;
procedure SET_EXTERNAL_SKELETON;
end SKELETON_MANAGER;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE symbol table routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION implements only a simple symbol table using open hashing
-- NOTES could be faster, but it isn't used much
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/symB.a,v 1.6 90/01/12 15:20:39 self Exp Locker: self $
with MISC_DEFS, MISC, NFA, TEXT_IO, INT_IO, TSTRING;
package body SYM is
use MISC_DEFS;
use TSTRING;
-- addsym - add symbol and definitions to symbol table
--
-- true is returned if the symbol already exists, and the change not made.
procedure ADDSYM(SYM, STR_DEF : in VSTRING;
INT_DEF : in INTEGER;
TABLE : in out HASH_TABLE;
TABLE_SIZE : in INTEGER;
RESULT : out BOOLEAN) is
HASH_VAL : INTEGER := HASHFUNCT(SYM, TABLE_SIZE);
SYM_ENTRY : HASH_LINK := TABLE(HASH_VAL);
NEW_ENTRY, SUCCESSOR : HASH_LINK;
begin
while (SYM_ENTRY /= null) loop
if (SYM = SYM_ENTRY.NAME) then
-- entry already exists
RESULT := TRUE;
return;
end if;
SYM_ENTRY := SYM_ENTRY.NEXT;
end loop;
-- create new entry
NEW_ENTRY := new HASH_ENTRY;
SUCCESSOR := TABLE(HASH_VAL);
if ((SUCCESSOR /= null)) then
NEW_ENTRY.NEXT := SUCCESSOR;
SUCCESSOR.PREV := NEW_ENTRY;
else
NEW_ENTRY.NEXT := null;
end if;
NEW_ENTRY.PREV := null;
NEW_ENTRY.NAME := SYM;
NEW_ENTRY.STR_VAL := STR_DEF;
NEW_ENTRY.INT_VAL := INT_DEF;
TABLE(HASH_VAL) := NEW_ENTRY;
RESULT := FALSE;
return;
exception
when STORAGE_ERROR =>
MISC.AFLEXFATAL("symbol table memory allocation failed");
end ADDSYM;
-- cclinstal - save the text of a character class
procedure CCLINSTAL(CCLTXT : in VSTRING;
CCLNUM : in INTEGER) is
-- we don't bother checking the return status because we are not called
-- unless the symbol is new
DUMMY : BOOLEAN;
begin
ADDSYM(CCLTXT, NUL, CCLNUM, CCLTAB, CCL_HASH_SIZE, DUMMY);
end CCLINSTAL;
-- ccllookup - lookup the number associated with character class text
function CCLLOOKUP(CCLTXT : in VSTRING) return INTEGER is
begin
return FINDSYM(CCLTXT, CCLTAB, CCL_HASH_SIZE).INT_VAL;
end CCLLOOKUP;
-- findsym - find symbol in symbol table
function FINDSYM(SYMBOL : in VSTRING;
TABLE : in HASH_TABLE;
TABLE_SIZE : in INTEGER) return HASH_LINK is
SYM_ENTRY : HASH_LINK := TABLE(HASHFUNCT(SYMBOL, TABLE_SIZE));
EMPTY_ENTRY : HASH_LINK;
begin
while (SYM_ENTRY /= null) loop
if (SYMBOL = SYM_ENTRY.NAME) then
return SYM_ENTRY;
end if;
SYM_ENTRY := SYM_ENTRY.NEXT;
end loop;
EMPTY_ENTRY := new HASH_ENTRY;
EMPTY_ENTRY.all := (null, null, NUL, NUL, 0);
return EMPTY_ENTRY;
exception
when STORAGE_ERROR =>
MISC.AFLEXFATAL("dynamic memory failure in findsym()");
return EMPTY_ENTRY;
end FINDSYM;
-- hashfunct - compute the hash value for "str" and hash size "hash_size"
function HASHFUNCT(STR : in VSTRING;
HASH_SIZE : in INTEGER) return INTEGER is
HASHVAL, LOCSTR : INTEGER;
begin
HASHVAL := 0;
LOCSTR := TSTRING.FIRST;
while (LOCSTR <= TSTRING.LEN(STR)) loop
HASHVAL := ((HASHVAL*2) + CHARACTER'POS(CHAR(STR, LOCSTR))) mod HASH_SIZE
;
LOCSTR := LOCSTR + 1;
end loop;
return HASHVAL;
end HASHFUNCT;
--ndinstal - install a name definition
procedure NDINSTAL(ND, DEF : in VSTRING) is
RESULT : BOOLEAN;
begin
ADDSYM(ND, DEF, 0, NDTBL, NAME_TABLE_HASH_SIZE, RESULT);
if (RESULT) then
MISC.SYNERR("name defined twice");
end if;
end NDINSTAL;
-- ndlookup - lookup a name definition
function NDLOOKUP(ND : in VSTRING) return VSTRING is
begin
return FINDSYM(ND, NDTBL, NAME_TABLE_HASH_SIZE).STR_VAL;
end NDLOOKUP;
-- scinstal - make a start condition
--
-- NOTE
-- the start condition is Exclusive if xcluflg is true
procedure SCINSTAL(STR : in VSTRING;
XCLUFLG : in BOOLEAN) is
-- bit of a hack. We know how the default start-condition is
-- declared, and don't put out a define for it, because it
-- would come out as "#define 0 1"
-- actually, this is no longer the case. The default start-condition
-- is now called "INITIAL". But we keep the following for the sake
-- of future robustness.
RESULT : BOOLEAN;
begin
if (STR /= VSTR("0")) then
TSTRING.PUT(DEF_FILE, STR);
TEXT_IO.PUT(DEF_FILE, " : constant := ");
INT_IO.PUT(DEF_FILE, LASTSC, 1);
TEXT_IO.PUT_LINE(DEF_FILE, ";");
end if;
LASTSC := LASTSC + 1;
if (LASTSC >= CURRENT_MAX_SCS) then
CURRENT_MAX_SCS := CURRENT_MAX_SCS + MAX_SCS_INCREMENT;
NUM_REALLOCS := NUM_REALLOCS + 1;
REALLOCATE_INTEGER_ARRAY(SCSET, CURRENT_MAX_SCS);
REALLOCATE_INTEGER_ARRAY(SCBOL, CURRENT_MAX_SCS);
REALLOCATE_BOOLEAN_ARRAY(SCXCLU, CURRENT_MAX_SCS);
REALLOCATE_BOOLEAN_ARRAY(SCEOF, CURRENT_MAX_SCS);
REALLOCATE_VSTRING_ARRAY(SCNAME, CURRENT_MAX_SCS);
REALLOCATE_INTEGER_ARRAY(ACTVSC, CURRENT_MAX_SCS);
end if;
SCNAME(LASTSC) := STR;
ADDSYM(SCNAME(LASTSC), NUL, LASTSC, SCTBL, START_COND_HASH_SIZE, RESULT);
if (RESULT) then
MISC.AFLEXERROR("start condition " & STR & " declared twice");
end if;
SCSET(LASTSC) := NFA.MKSTATE(SYM_EPSILON);
SCBOL(LASTSC) := NFA.MKSTATE(SYM_EPSILON);
SCXCLU(LASTSC) := XCLUFLG;
SCEOF(LASTSC) := FALSE;
end SCINSTAL;
-- sclookup - lookup the number associated with a start condition
function SCLOOKUP(STR : in VSTRING) return INTEGER is
begin
return FINDSYM(STR, SCTBL, START_COND_HASH_SIZE).INT_VAL;
end SCLOOKUP;
end SYM;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE symbol table routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION implements only a simple symbol table using open hashing
-- NOTES could be faster, but it isn't used much
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/symS.a,v 1.4 90/01/12 15:20:42 self Exp Locker: self $
with TSTRING;
with MISC_DEFS;
package SYM is
use TSTRING;
use MISC_DEFS;
procedure ADDSYM(SYM, STR_DEF : in VSTRING;
INT_DEF : in INTEGER;
TABLE : in out HASH_TABLE;
TABLE_SIZE : in INTEGER;
RESULT : out BOOLEAN);
-- result indicates success
procedure CCLINSTAL(CCLTXT : in VSTRING;
CCLNUM : in INTEGER);
function CCLLOOKUP(CCLTXT : in VSTRING) return INTEGER;
function FINDSYM(SYMBOL : in VSTRING;
TABLE : in HASH_TABLE;
TABLE_SIZE : in INTEGER) return HASH_LINK;
function HASHFUNCT(STR : in VSTRING;
HASH_SIZE : in INTEGER) return INTEGER;
procedure NDINSTAL(ND, DEF : in VSTRING);
function NDLOOKUP(ND : in VSTRING) return VSTRING;
procedure SCINSTAL(STR : in VSTRING;
XCLUFLG : in BOOLEAN);
function SCLOOKUP(STR : in VSTRING) return INTEGER;
end SYM;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE table compression routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION used for compressed tables only
-- NOTES somewhat complicated but works fast and generates efficient scanners
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/tblcmpB.a,v 1.8 90/01/12 15:20:43 self Exp Locker: self $
with DFA, ECS, MISC_DEFS; use MISC_DEFS;
package body TBLCMP is
-- bldtbl - build table entries for dfa state
--
-- synopsis
-- int state[numecs], statenum, totaltrans, comstate, comfreq;
-- bldtbl( state, statenum, totaltrans, comstate, comfreq );
--
-- State is the statenum'th dfa state. It is indexed by equivalence class and
-- gives the number of the state to enter for a given equivalence class.
-- totaltrans is the total number of transitions out of the state. Comstate
-- is that state which is the destination of the most transitions out of State.
-- Comfreq is how many transitions there are out of State to Comstate.
--
-- A note on terminology:
-- "protos" are transition tables which have a high probability of
-- either being redundant (a state processed later will have an identical
-- transition table) or nearly redundant (a state processed later will have
-- many of the same out-transitions). A "most recently used" queue of
-- protos is kept around with the hope that most states will find a proto
-- which is similar enough to be usable, and therefore compacting the
-- output tables.
-- "templates" are a special type of proto. If a transition table is
-- homogeneous or nearly homogeneous (all transitions go to the same
-- destination) then the odds are good that future states will also go
-- to the same destination state on basically the same character set.
-- These homogeneous states are so common when dealing with large rule
-- sets that they merit special attention. If the transition table were
-- simply made into a proto, then (typically) each subsequent, similar
-- state will differ from the proto for two out-transitions. One of these
-- out-transitions will be that character on which the proto does not go
-- to the common destination, and one will be that character on which the
-- state does not go to the common destination. Templates, on the other
-- hand, go to the common state on EVERY transition character, and therefore
-- cost only one difference.
procedure BLDTBL(STATE : in
UNBOUNDED_INT_ARRAY;
STATENUM, TOTALTRANS, COMSTATE, COMFREQ : in INTEGER) is
EXTPTR : INTEGER;
subtype CARRAY is UNBOUNDED_INT_ARRAY(0 .. CSIZE + 1);
EXTRCT : array(0 .. 1) of CARRAY;
MINDIFF, MINPROT, I, D : INTEGER;
CHECKCOM : BOOLEAN;
LOCAL_COMSTATE : INTEGER;
begin
-- If extptr is 0 then the first array of extrct holds the result of the
-- "best difference" to date, which is those transitions which occur in
-- "state" but not in the proto which, to date, has the fewest differences
-- between itself and "state". If extptr is 1 then the second array of
-- extrct hold the best difference. The two arrays are toggled
-- between so that the best difference to date can be kept around and
-- also a difference just created by checking against a candidate "best"
-- proto.
LOCAL_COMSTATE := COMSTATE;
EXTPTR := 0;
-- if the state has too few out-transitions, don't bother trying to
-- compact its tables
if ((TOTALTRANS*100) < (NUMECS*PROTO_SIZE_PERCENTAGE)) then
MKENTRY(STATE, NUMECS, STATENUM, JAMSTATE_CONST, TOTALTRANS);
else
-- checkcom is true if we should only check "state" against
-- protos which have the same "comstate" value
CHECKCOM := COMFREQ*100 > TOTALTRANS*CHECK_COM_PERCENTAGE;
MINPROT := FIRSTPROT;
MINDIFF := TOTALTRANS;
if (CHECKCOM) then
-- find first proto which has the same "comstate"
I := FIRSTPROT;
while (I /= NIL) loop
if (PROTCOMST(I) = LOCAL_COMSTATE) then
MINPROT := I;
TBLDIFF(STATE, MINPROT, EXTRCT(EXTPTR), MINDIFF);
exit;
end if;
I := PROTNEXT(I);
end loop;
else
-- since we've decided that the most common destination out
-- of "state" does not occur with a high enough frequency,
-- we set the "comstate" to zero, assuring that if this state
-- is entered into the proto list, it will not be considered
-- a template.
LOCAL_COMSTATE := 0;
if (FIRSTPROT /= NIL) then
MINPROT := FIRSTPROT;
TBLDIFF(STATE, MINPROT, EXTRCT(EXTPTR), MINDIFF);
end if;
end if;
-- we now have the first interesting proto in "minprot". If
-- it matches within the tolerances set for the first proto,
-- we don't want to bother scanning the rest of the proto list
-- to see if we have any other reasonable matches.
if (MINDIFF*100 > TOTALTRANS*FIRST_MATCH_DIFF_PERCENTAGE) then
-- not a good enough match. Scan the rest of the protos
I := MINPROT;
while (I /= NIL) loop
TBLDIFF(STATE, I, EXTRCT(1 - EXTPTR), D);
if (D < MINDIFF) then
EXTPTR := 1 - EXTPTR;
MINDIFF := D;
MINPROT := I;
end if;
I := PROTNEXT(I);
end loop;
end if;
-- check if the proto we've decided on as our best bet is close
-- enough to the state we want to match to be usable
if (MINDIFF*100 > TOTALTRANS*ACCEPTABLE_DIFF_PERCENTAGE) then
-- no good. If the state is homogeneous enough, we make a
-- template out of it. Otherwise, we make a proto.
if (COMFREQ*100 >= TOTALTRANS*TEMPLATE_SAME_PERCENTAGE) then
MKTEMPLATE(STATE, STATENUM, LOCAL_COMSTATE);
else
MKPROT(STATE, STATENUM, LOCAL_COMSTATE);
MKENTRY(STATE, NUMECS, STATENUM, JAMSTATE_CONST, TOTALTRANS);
end if;
else
-- use the proto
MKENTRY(EXTRCT(EXTPTR), NUMECS, STATENUM, PROTTBL(MINPROT), MINDIFF);
-- if this state was sufficiently different from the proto
-- we built it from, make it, too, a proto
if (MINDIFF*100 >= TOTALTRANS*NEW_PROTO_DIFF_PERCENTAGE) then
MKPROT(STATE, STATENUM, LOCAL_COMSTATE);
end if;
-- since mkprot added a new proto to the proto queue, it's possible
-- that "minprot" is no longer on the proto queue (if it happened
-- to have been the last entry, it would have been bumped off).
-- If it's not there, then the new proto took its physical place
-- (though logically the new proto is at the beginning of the
-- queue), so in that case the following call will do nothing.
MV2FRONT(MINPROT);
end if;
end if;
end BLDTBL;
-- cmptmps - compress template table entries
--
-- template tables are compressed by using the 'template equivalence
-- classes', which are collections of transition character equivalence
-- classes which always appear together in templates - really meta-equivalence
-- classes. until this point, the tables for templates have been stored
-- up at the top end of the nxt array; they will now be compressed and have
-- table entries made for them.
procedure CMPTMPS is
TMPSTORAGE : C_SIZE_ARRAY;
TOTALTRANS, TRANS : INTEGER;
begin
PEAKPAIRS := NUMTEMPS*NUMECS + TBLEND;
if (USEMECS) then
-- create equivalence classes base on data gathered on template
-- transitions
ECS.CRE8ECS(TECFWD, TECBCK, NUMECS, NUMMECS);
else
NUMMECS := NUMECS;
end if;
if (LASTDFA + NUMTEMPS + 1 >= CURRENT_MAX_DFAS) then
DFA.INCREASE_MAX_DFAS;
end if;
-- loop through each template
for I in 1 .. NUMTEMPS loop
TOTALTRANS := 0;
-- number of non-jam transitions out of this template
for J in 1 .. NUMECS loop
TRANS := TNXT(NUMECS*I + J);
if (USEMECS) then
-- the absolute value of tecbck is the meta-equivalence class
-- of a given equivalence class, as set up by cre8ecs
if (TECBCK(J) > 0) then
TMPSTORAGE(TECBCK(J)) := TRANS;
if (TRANS > 0) then
TOTALTRANS := TOTALTRANS + 1;
end if;
end if;
else
TMPSTORAGE(J) := TRANS;
if (TRANS > 0) then
TOTALTRANS := TOTALTRANS + 1;
end if;
end if;
end loop;
-- it is assumed (in a rather subtle way) in the skeleton that
-- if we're using meta-equivalence classes, the def[] entry for
-- all templates is the jam template, i.e., templates never default
-- to other non-jam table entries (e.g., another template)
-- leave room for the jam-state after the last real state
MKENTRY(TMPSTORAGE, NUMMECS, LASTDFA + I + 1, JAMSTATE_CONST, TOTALTRANS)
;
end loop;
end CMPTMPS;
-- expand_nxt_chk - expand the next check arrays
procedure EXPAND_NXT_CHK is
OLD_MAX : INTEGER := CURRENT_MAX_XPAIRS;
begin
CURRENT_MAX_XPAIRS := CURRENT_MAX_XPAIRS + MAX_XPAIRS_INCREMENT;
NUM_REALLOCS := NUM_REALLOCS + 1;
REALLOCATE_INTEGER_ARRAY(NXT, CURRENT_MAX_XPAIRS);
REALLOCATE_INTEGER_ARRAY(CHK, CURRENT_MAX_XPAIRS);
for I in OLD_MAX .. CURRENT_MAX_XPAIRS loop
CHK(I) := 0;
end loop;
end EXPAND_NXT_CHK;
-- find_table_space - finds a space in the table for a state to be placed
--
-- State is the state to be added to the full speed transition table.
-- Numtrans is the number of out-transitions for the state.
--
-- find_table_space() returns the position of the start of the first block (in
-- chk) able to accommodate the state
--
-- In determining if a state will or will not fit, find_table_space() must take
-- into account the fact that an end-of-buffer state will be added at [0],
-- and an action number will be added in [-1].
function FIND_TABLE_SPACE(STATE : in UNBOUNDED_INT_ARRAY;
NUMTRANS : in INTEGER) return INTEGER is
-- firstfree is the position of the first possible occurrence of two
-- consecutive unused records in the chk and nxt arrays
I : INTEGER;
STATE_PTR, CHK_PTR, PTR_TO_LAST_ENTRY_IN_STATE : INT_PTR;
CNT, SCNT : INTEGER;
-- if there are too many out-transitions, put the state at the end of
-- nxt and chk
begin
if (NUMTRANS > MAX_XTIONS_FULL_INTERIOR_FIT) then
-- if table is empty, return the first available spot in chk/nxt,
-- which should be 1
if (TBLEND < 2) then
return (1);
end if;
I := TBLEND - NUMECS;
-- start searching for table space near the
-- end of chk/nxt arrays
else
I := FIRSTFREE;
-- start searching for table space from the
-- beginning (skipping only the elements
-- which will definitely not hold the new
-- state)
end if;
loop
-- loops until a space is found
if (I + NUMECS > CURRENT_MAX_XPAIRS) then
EXPAND_NXT_CHK;
end if;
-- loops until space for end-of-buffer and action number are found
loop
if (CHK(I - 1) = 0) then
-- check for action number space
if (CHK(I) = 0) then
-- check for end-of-buffer space
exit;
else
I := I + 2;
-- since i != 0, there is no use checking to
-- see if (++i) - 1 == 0, because that's the
-- same as i == 0, so we skip a space
end if;
else
I := I + 1;
end if;
if (I + NUMECS > CURRENT_MAX_XPAIRS) then
EXPAND_NXT_CHK;
end if;
end loop;
-- if we started search from the beginning, store the new firstfree for
-- the next call of find_table_space()
if (NUMTRANS <= MAX_XTIONS_FULL_INTERIOR_FIT) then
FIRSTFREE := I + 1;
end if;
-- check to see if all elements in chk (and therefore nxt) that are
-- needed for the new state have not yet been taken
CNT := I + 1;
SCNT := 1;
while (CNT /= I + NUMECS + 1) loop
if ((STATE(SCNT) /= 0) and (CHK(CNT) /= 0)) then
exit;
end if;
SCNT := SCNT + 1;
CNT := CNT + 1;
end loop;
if (CNT = I + NUMECS + 1) then
return I;
else
I := I + 1;
end if;
end loop;
end FIND_TABLE_SPACE;
-- inittbl - initialize transition tables
--
-- Initializes "firstfree" to be one beyond the end of the table. Initializes
-- all "chk" entries to be zero. Note that templates are built in their
-- own tbase/tdef tables. They are shifted down to be contiguous
-- with the non-template entries during table generation.
procedure INITTBL is
begin
for I in 0 .. CURRENT_MAX_XPAIRS loop
CHK(I) := 0;
end loop;
TBLEND := 0;
FIRSTFREE := TBLEND + 1;
NUMTEMPS := 0;
if (USEMECS) then
-- set up doubly-linked meta-equivalence classes
-- these are sets of equivalence classes which all have identical
-- transitions out of TEMPLATES
TECBCK(1) := NIL;
for I in 2 .. NUMECS loop
TECBCK(I) := I - 1;
TECFWD(I - 1) := I;
end loop;
TECFWD(NUMECS) := NIL;
end if;
end INITTBL;
-- mkdeftbl - make the default, "jam" table entries
procedure MKDEFTBL is
begin
JAMSTATE := LASTDFA + 1;
TBLEND := TBLEND + 1;
-- room for transition on end-of-buffer character
if (TBLEND + NUMECS > CURRENT_MAX_XPAIRS) then
EXPAND_NXT_CHK;
end if;
-- add in default end-of-buffer transition
NXT(TBLEND) := END_OF_BUFFER_STATE;
CHK(TBLEND) := JAMSTATE;
for I in 1 .. NUMECS loop
NXT(TBLEND + I) := 0;
CHK(TBLEND + I) := JAMSTATE;
end loop;
JAMBASE := TBLEND;
BASE(JAMSTATE) := JAMBASE;
DEF(JAMSTATE) := 0;
TBLEND := TBLEND + NUMECS;
NUMTEMPS := NUMTEMPS + 1;
end MKDEFTBL;
-- mkentry - create base/def and nxt/chk entries for transition array
--
-- "state" is a transition array "numchars" characters in size, "statenum"
-- is the offset to be used into the base/def tables, and "deflink" is the
-- entry to put in the "def" table entry. If "deflink" is equal to
-- "JAMSTATE", then no attempt will be made to fit zero entries of "state"
-- (i.e., jam entries) into the table. It is assumed that by linking to
-- "JAMSTATE" they will be taken care of. In any case, entries in "state"
-- marking transitions to "SAME_TRANS" are treated as though they will be
-- taken care of by whereever "deflink" points. "totaltrans" is the total
-- number of transitions out of the state. If it is below a certain threshold,
-- the tables are searched for an interior spot that will accommodate the
-- state array.
procedure MKENTRY(STATE : in
UNBOUNDED_INT_ARRAY;
NUMCHARS, STATENUM, DEFLINK, TOTALTRANS : in INTEGER) is
I, MINEC, MAXEC, BASEADDR, TBLBASE, TBLLAST : INTEGER;
begin
if (TOTALTRANS = 0) then
-- there are no out-transitions
if (DEFLINK = JAMSTATE_CONST) then
BASE(STATENUM) := JAMSTATE_CONST;
else
BASE(STATENUM) := 0;
end if;
DEF(STATENUM) := DEFLINK;
return;
end if;
MINEC := 1;
while (MINEC <= NUMCHARS) loop
if (STATE(MINEC) /= SAME_TRANS) then
if ((STATE(MINEC) /= 0) or (DEFLINK /= JAMSTATE_CONST)) then
exit;
end if;
end if;
MINEC := MINEC + 1;
end loop;
if (TOTALTRANS = 1) then
-- there's only one out-transition. Save it for later to fill
-- in holes in the tables.
STACK1(STATENUM, MINEC, STATE(MINEC), DEFLINK);
return;
end if;
MAXEC := NUMCHARS;
while (MAXEC >= 1) loop
if (STATE(MAXEC) /= SAME_TRANS) then
if ((STATE(MAXEC) /= 0) or (DEFLINK /= JAMSTATE_CONST)) then
exit;
end if;
end if;
MAXEC := MAXEC - 1;
end loop;
-- Whether we try to fit the state table in the middle of the table
-- entries we have already generated, or if we just take the state
-- table at the end of the nxt/chk tables, we must make sure that we
-- have a valid base address (i.e., non-negative). Note that not only are
-- negative base addresses dangerous at run-time (because indexing the
-- next array with one and a low-valued character might generate an
-- array-out-of-bounds error message), but at compile-time negative
-- base addresses denote TEMPLATES.
-- find the first transition of state that we need to worry about.
if (TOTALTRANS*100 <= NUMCHARS*INTERIOR_FIT_PERCENTAGE) then
-- attempt to squeeze it into the middle of the tabls
BASEADDR := FIRSTFREE;
while (BASEADDR < MINEC) loop
-- using baseaddr would result in a negative base address below
-- find the next free slot
BASEADDR := BASEADDR + 1;
while (CHK(BASEADDR) /= 0) loop
BASEADDR := BASEADDR + 1;
end loop;
end loop;
if (BASEADDR + MAXEC - MINEC >= CURRENT_MAX_XPAIRS) then
EXPAND_NXT_CHK;
end if;
I := MINEC;
while (I <= MAXEC) loop
if (STATE(I) /= SAME_TRANS) then
if ((STATE(I) /= 0) or (DEFLINK /= JAMSTATE_CONST)) then
if (CHK(BASEADDR + I - MINEC) /= 0) then
-- baseaddr unsuitable - find another
BASEADDR := BASEADDR + 1;
while ((BASEADDR < CURRENT_MAX_XPAIRS) and (CHK(BASEADDR) /= 0))
loop
BASEADDR := BASEADDR + 1;
end loop;
if (BASEADDR + MAXEC - MINEC >= CURRENT_MAX_XPAIRS) then
EXPAND_NXT_CHK;
end if;
-- reset the loop counter so we'll start all
-- over again next time it's incremented
I := MINEC - 1;
end if;
end if;
end if;
I := I + 1;
end loop;
else
-- ensure that the base address we eventually generate is
-- non-negative
BASEADDR := MAX(TBLEND + 1, MINEC);
end if;
TBLBASE := BASEADDR - MINEC;
TBLLAST := TBLBASE + MAXEC;
if (TBLLAST >= CURRENT_MAX_XPAIRS) then
EXPAND_NXT_CHK;
end if;
BASE(STATENUM) := TBLBASE;
DEF(STATENUM) := DEFLINK;
for J in MINEC .. MAXEC loop
if (STATE(J) /= SAME_TRANS) then
if ((STATE(J) /= 0) or (DEFLINK /= JAMSTATE_CONST)) then
NXT(TBLBASE + J) := STATE(J);
CHK(TBLBASE + J) := STATENUM;
end if;
end if;
end loop;
if (BASEADDR = FIRSTFREE) then
-- find next free slot in tables
FIRSTFREE := FIRSTFREE + 1;
while (CHK(FIRSTFREE) /= 0) loop
FIRSTFREE := FIRSTFREE + 1;
end loop;
end if;
TBLEND := MAX(TBLEND, TBLLAST);
end MKENTRY;
-- mk1tbl - create table entries for a state (or state fragment) which
-- has only one out-transition
procedure MK1TBL(STATE, SYM, ONENXT, ONEDEF : in INTEGER) is
begin
if (FIRSTFREE < SYM) then
FIRSTFREE := SYM;
end if;
while (CHK(FIRSTFREE) /= 0) loop
FIRSTFREE := FIRSTFREE + 1;
if (FIRSTFREE >= CURRENT_MAX_XPAIRS) then
EXPAND_NXT_CHK;
end if;
end loop;
BASE(STATE) := FIRSTFREE - SYM;
DEF(STATE) := ONEDEF;
CHK(FIRSTFREE) := STATE;
NXT(FIRSTFREE) := ONENXT;
if (FIRSTFREE > TBLEND) then
TBLEND := FIRSTFREE;
FIRSTFREE := FIRSTFREE + 1;
if (FIRSTFREE >= CURRENT_MAX_XPAIRS) then
EXPAND_NXT_CHK;
end if;
end if;
end MK1TBL;
-- mkprot - create new proto entry
procedure MKPROT(STATE : in UNBOUNDED_INT_ARRAY;
STATENUM, COMSTATE : in INTEGER) is
SLOT, TBLBASE : INTEGER;
begin
NUMPROTS := NUMPROTS + 1;
if ((NUMPROTS >= MSP) or (NUMECS*NUMPROTS >= PROT_SAVE_SIZE)) then
-- gotta make room for the new proto by dropping last entry in
-- the queue
SLOT := LASTPROT;
LASTPROT := PROTPREV(LASTPROT);
PROTNEXT(LASTPROT) := NIL;
else
SLOT := NUMPROTS;
end if;
PROTNEXT(SLOT) := FIRSTPROT;
if (FIRSTPROT /= NIL) then
PROTPREV(FIRSTPROT) := SLOT;
end if;
FIRSTPROT := SLOT;
PROTTBL(SLOT) := STATENUM;
PROTCOMST(SLOT) := COMSTATE;
-- copy state into save area so it can be compared with rapidly
TBLBASE := NUMECS*(SLOT - 1);
for I in 1 .. NUMECS loop
PROTSAVE(TBLBASE + I) := STATE(I + STATE'FIRST);
end loop;
end MKPROT;
-- mktemplate - create a template entry based on a state, and connect the state
-- to it
procedure MKTEMPLATE(STATE : in UNBOUNDED_INT_ARRAY;
STATENUM, COMSTATE : in INTEGER) is
NUMDIFF, TMPBASE : INTEGER;
TMP : C_SIZE_ARRAY;
subtype TARRAY is CHAR_ARRAY(0 .. CSIZE);
TRANSSET : TARRAY;
TSPTR : INTEGER;
begin
NUMTEMPS := NUMTEMPS + 1;
TSPTR := 0;
-- calculate where we will temporarily store the transition table
-- of the template in the tnxt[] array. The final transition table
-- gets created by cmptmps()
TMPBASE := NUMTEMPS*NUMECS;
if (TMPBASE + NUMECS >= CURRENT_MAX_TEMPLATE_XPAIRS) then
CURRENT_MAX_TEMPLATE_XPAIRS := CURRENT_MAX_TEMPLATE_XPAIRS +
MAX_TEMPLATE_XPAIRS_INCREMENT;
NUM_REALLOCS := NUM_REALLOCS + 1;
REALLOCATE_INTEGER_ARRAY(TNXT, CURRENT_MAX_TEMPLATE_XPAIRS);
end if;
for I in 1 .. NUMECS loop
if (STATE(I) = 0) then
TNXT(TMPBASE + I) := 0;
else
TRANSSET(TSPTR) := CHARACTER'VAL(I);
TSPTR := TSPTR + 1;
TNXT(TMPBASE + I) := COMSTATE;
end if;
end loop;
if (USEMECS) then
ECS.MKECCL(TRANSSET, TSPTR, TECFWD, TECBCK, NUMECS);
end if;
MKPROT(TNXT(TMPBASE .. CURRENT_MAX_TEMPLATE_XPAIRS), -NUMTEMPS, COMSTATE);
-- we rely on the fact that mkprot adds things to the beginning
-- of the proto queue
TBLDIFF(STATE, FIRSTPROT, TMP, NUMDIFF);
MKENTRY(TMP, NUMECS, STATENUM, -NUMTEMPS, NUMDIFF);
end MKTEMPLATE;
-- mv2front - move proto queue element to front of queue
procedure MV2FRONT(QELM : in INTEGER) is
begin
if (FIRSTPROT /= QELM) then
if (QELM = LASTPROT) then
LASTPROT := PROTPREV(LASTPROT);
end if;
PROTNEXT(PROTPREV(QELM)) := PROTNEXT(QELM);
if (PROTNEXT(QELM) /= NIL) then
PROTPREV(PROTNEXT(QELM)) := PROTPREV(QELM);
end if;
PROTPREV(QELM) := NIL;
PROTNEXT(QELM) := FIRSTPROT;
PROTPREV(FIRSTPROT) := QELM;
FIRSTPROT := QELM;
end if;
end MV2FRONT;
-- place_state - place a state into full speed transition table
--
-- State is the statenum'th state. It is indexed by equivalence class and
-- gives the number of the state to enter for a given equivalence class.
-- Transnum is the number of out-transitions for the state.
procedure PLACE_STATE(STATE : in UNBOUNDED_INT_ARRAY;
STATENUM, TRANSNUM : in INTEGER) is
I : INTEGER;
POSITION : INTEGER := FIND_TABLE_SPACE(STATE, TRANSNUM);
begin
-- base is the table of start positions
BASE(STATENUM) := POSITION;
-- put in action number marker; this non-zero number makes sure that
-- find_table_space() knows that this position in chk/nxt is taken
-- and should not be used for another accepting number in another state
CHK(POSITION - 1) := 1;
-- put in end-of-buffer marker; this is for the same purposes as above
CHK(POSITION) := 1;
-- place the state into chk and nxt
I := 1;
while (I <= NUMECS) loop
if (STATE(I) /= 0) then
CHK(POSITION + I) := I;
NXT(POSITION + I) := STATE(I);
end if;
I := I + 1;
end loop;
if (POSITION + NUMECS > TBLEND) then
TBLEND := POSITION + NUMECS;
end if;
end PLACE_STATE;
-- stack1 - save states with only one out-transition to be processed later
--
-- if there's room for another state one the "one-transition" stack, the
-- state is pushed onto it, to be processed later by mk1tbl. If there's
-- no room, we process the sucker right now.
procedure STACK1(STATENUM, SYM, NEXTSTATE, DEFLINK : in INTEGER) is
begin
if (ONESP >= ONE_STACK_SIZE - 1) then
MK1TBL(STATENUM, SYM, NEXTSTATE, DEFLINK);
else
ONESP := ONESP + 1;
ONESTATE(ONESP) := STATENUM;
ONESYM(ONESP) := SYM;
ONENEXT(ONESP) := NEXTSTATE;
ONEDEF(ONESP) := DEFLINK;
end if;
end STACK1;
-- tbldiff - compute differences between two state tables
--
-- "state" is the state array which is to be extracted from the pr'th
-- proto. "pr" is both the number of the proto we are extracting from
-- and an index into the save area where we can find the proto's complete
-- state table. Each entry in "state" which differs from the corresponding
-- entry of "pr" will appear in "ext".
-- Entries which are the same in both "state" and "pr" will be marked
-- as transitions to "SAME_TRANS" in "ext". The total number of differences
-- between "state" and "pr" is returned as function value. Note that this
-- number is "numecs" minus the number of "SAME_TRANS" entries in "ext".
procedure TBLDIFF(STATE : in UNBOUNDED_INT_ARRAY;
PR : in INTEGER;
EXT : out UNBOUNDED_INT_ARRAY;
RESULT : out INTEGER) is
SP : INTEGER := 0;
EP : INTEGER := 0;
NUMDIFF : INTEGER := 0;
PROTP : INTEGER;
begin
PROTP := NUMECS*(PR - 1);
for I in reverse 1 .. NUMECS loop
PROTP := PROTP + 1;
SP := SP + 1;
if (PROTSAVE(PROTP) = STATE(SP)) then
EP := EP + 1;
EXT(EP) := SAME_TRANS;
else
EP := EP + 1;
EXT(EP) := STATE(SP);
NUMDIFF := NUMDIFF + 1;
end if;
end loop;
RESULT := NUMDIFF;
return;
end TBLDIFF;
end TBLCMP;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE table compression routines
-- AUTHOR: John Self (UCI)
-- DESCRIPTION used for compressed tables only
-- NOTES somewhat complicated but works fast and generates efficient scanners
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/tblcmpS.a,v 1.3 90/01/12 15:20:47 self Exp Locker: self $
with MISC_DEFS; use MISC_DEFS;
package TBLCMP is
-- bldtbl - build table entries for dfa state
procedure BLDTBL(STATE : in
UNBOUNDED_INT_ARRAY;
STATENUM, TOTALTRANS, COMSTATE, COMFREQ : in INTEGER);
procedure CMPTMPS;
-- expand_nxt_chk - expand the next check arrays
procedure EXPAND_NXT_CHK;
-- find_table_space - finds a space in the table for a state to be placed
function FIND_TABLE_SPACE(STATE : in UNBOUNDED_INT_ARRAY;
NUMTRANS : in INTEGER) return INTEGER;
-- inittbl - initialize transition tables
procedure INITTBL;
-- mkdeftbl - make the default, "jam" table entries
procedure MKDEFTBL;
-- mkentry - create base/def and nxt/chk entries for transition array
procedure MKENTRY(STATE : in
UNBOUNDED_INT_ARRAY;
NUMCHARS, STATENUM, DEFLINK, TOTALTRANS : in INTEGER);
-- mk1tbl - create table entries for a state (or state fragment) which
-- has only one out-transition
procedure MK1TBL(STATE, SYM, ONENXT, ONEDEF : in INTEGER);
-- mkprot - create new proto entry
procedure MKPROT(STATE : in UNBOUNDED_INT_ARRAY;
STATENUM, COMSTATE : in INTEGER);
-- mktemplate - create a template entry based on a state, and connect the state
-- to it
procedure MKTEMPLATE(STATE : in UNBOUNDED_INT_ARRAY;
STATENUM, COMSTATE : in INTEGER);
-- mv2front - move proto queue element to front of queue
procedure MV2FRONT(QELM : in INTEGER);
-- place_state - place a state into full speed transition table
procedure PLACE_STATE(STATE : in UNBOUNDED_INT_ARRAY;
STATENUM, TRANSNUM : in INTEGER);
-- stack1 - save states with only one out-transition to be processed later
procedure STACK1(STATENUM, SYM, NEXTSTATE, DEFLINK : in INTEGER);
-- tbldiff - compute differences between two state tables
procedure TBLDIFF(STATE : in UNBOUNDED_INT_ARRAY;
PR : in INTEGER;
EXT : out UNBOUNDED_INT_ARRAY;
RESULT : out INTEGER);
end TBLCMP;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE template manager
-- AUTHOR: John Self (UCI)
-- DESCRIPTION supports output of internalized templates for the IO and DFA
-- packages.
-- NOTES This package is quite a memory hog, and is really only useful on
-- virtual memory systems. It could use an external file to store the
-- templates like the skeleton manager. This would save memory at the
-- cost of a slight reduction in speed and the necessity of keeping
-- copies of the template files in a known place.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/template_managerB.a,v 1.20 90/10/15 20:00:53 self Exp Locker: self $
with FILE_STRING, MISC_DEFS, TEXT_IO, EXTERNAL_FILE_MANAGER, MISC, TSTRING; use
FILE_STRING, MISC_DEFS, TEXT_IO;
package body TEMPLATE_MANAGER is
type FILE_ARRAY is array(POSITIVE range <>) of VSTRING;
DFA_TEMPLATE : FILE_ARRAY(1 .. 66) := (
--DFA TEMPLATE START
VSTR("yytext_ptr : integer; -- points to start of yytext in buffer"),
VSTR(""),
VSTR("-- yy_ch_buf has to be 2 characters longer than YY_BUF_SIZE because we need"),
VSTR("-- to put in 2 end-of-buffer characters (this is explained where it is"),
VSTR("-- done) at the end of yy_ch_buf"),
VSTR("YY_READ_BUF_SIZE : constant integer := 8192;"),
VSTR("YY_BUF_SIZE : constant integer := YY_READ_BUF_SIZE * 2; -- size of input buffer"),
VSTR("type unbounded_character_array is array(integer range <>) of character;"),
VSTR("subtype ch_buf_type is unbounded_character_array(0..YY_BUF_SIZE + 1);"),
VSTR("yy_ch_buf : ch_buf_type;"), VSTR("yy_cp, yy_bp : integer;"),
VSTR(""),
VSTR("-- yy_hold_char holds the character lost when yytext is formed"),
VSTR("yy_hold_char : character;"),
VSTR("yy_c_buf_p : integer; -- points to current character in buffer"),
VSTR(""),
VSTR("function YYText return string;"),
VSTR("function YYLength return integer;"),
VSTR("procedure YY_DO_BEFORE_ACTION;"),
VSTR("--These variables are needed between calls to YYLex."),
VSTR("yy_init : boolean := true; -- do we need to initialize YYLex?"),
VSTR("yy_start : integer := 0; -- current start state number"),
VSTR("subtype yy_state_type is integer;"),
VSTR("yy_last_accepting_state : yy_state_type;"),
VSTR("yy_last_accepting_cpos : integer;"), VSTR("%%"),
VSTR("function YYText return string is"),
VSTR(" i : integer;"),
VSTR(" str_loc : integer := 1;"),
VSTR(" buffer : string(1..1024);"),
VSTR(" EMPTY_STRING : constant string := """";"),
VSTR("begin"),
VSTR(" -- find end of buffer"),
VSTR(" i := yytext_ptr;"),
VSTR(" while ( yy_ch_buf(i) /= ASCII.NUL ) loop"),
VSTR(" buffer(str_loc ) := yy_ch_buf(i);"),
VSTR(" i := i + 1;"),
VSTR(" str_loc := str_loc + 1;"),
VSTR(" end loop;"),
VSTR("-- return yy_ch_buf(yytext_ptr.. i - 1);"),
VSTR(""),
VSTR(" if (str_loc < 2) then"),
VSTR(" return EMPTY_STRING;"),
VSTR(" else"),
VSTR(" return buffer(1..str_loc-1);"),
VSTR(" end if;"),
VSTR(""),
VSTR("end;"),
VSTR(""),
VSTR("-- returns the length of the matched text"),
VSTR("function YYLength return integer is"),
VSTR("begin"), VSTR(" return yy_cp - yy_bp;"),
VSTR("end YYLength;"),
VSTR(""),
VSTR("-- done after the current pattern has been matched and before the"),
VSTR("-- corresponding action - sets up yytext"),
VSTR(""),
VSTR("procedure YY_DO_BEFORE_ACTION is"),
VSTR("begin"),
VSTR(" yytext_ptr := yy_bp;"),
VSTR(" yy_hold_char := yy_ch_buf(yy_cp);"),
VSTR(" yy_ch_buf(yy_cp) := ASCII.NUL;"),
VSTR(" yy_c_buf_p := yy_cp;"),
VSTR("end YY_DO_BEFORE_ACTION;"),
VSTR("")
--DFA TEMPLATE END
);
DFA_CURRENT_LINE : INTEGER := 1;
IO_TEMPLATE : FILE_ARRAY(1 .. 264) := (
--IO TEMPLATE START
VSTR("with text_io; use text_io;"),
VSTR(""),
VSTR("%%"),
VSTR("NULL_IN_INPUT : exception;"),
VSTR("AFLEX_INTERNAL_ERROR : exception;"),
VSTR("UNEXPECTED_LAST_MATCH : exception;"),
VSTR("PUSHBACK_OVERFLOW : exception;"),
VSTR("AFLEX_SCANNER_JAMMED : exception;"),
VSTR("type eob_action_type is ( EOB_ACT_RESTART_SCAN,"),
VSTR(" EOB_ACT_END_OF_FILE,"),
VSTR(" EOB_ACT_LAST_MATCH );"),
VSTR("YY_END_OF_BUFFER_CHAR : constant character:= ASCII.NUL;"),
VSTR("yy_n_chars : integer; -- number of characters read into yy_ch_buf"),
VSTR(""),
VSTR("-- true when we've seen an EOF for the current input file"),
VSTR("yy_eof_has_been_seen : boolean;"), VSTR(""),
VSTR("procedure YY_INPUT(buf: out unbounded_character_array; result: out integer; max_size: in integer);"),
VSTR("function yy_get_next_buffer return eob_action_type;"),
VSTR("procedure yyunput( c : character; yy_bp: in out integer );"),
VSTR("procedure unput(c : character);"),
VSTR("function input return character;"),
VSTR("procedure output(c : character);"),
VSTR("function yywrap return boolean;"),
VSTR("procedure Open_Input(fname : in String);"),
VSTR("procedure Close_Input;"),
VSTR("procedure Create_Output(fname : in String := """");"),
VSTR("procedure Close_Output;"),
VSTR("%%"),
VSTR("-- gets input and stuffs it into 'buf'. number of characters read, or YY_NULL,"),
VSTR("-- is returned in 'result'."),
VSTR(""),
VSTR("procedure YY_INPUT(buf: out unbounded_character_array; result: out integer; max_size: in integer) is"),
VSTR(" c : character;"),
VSTR(" i : integer := 1;"),
VSTR(" loc : integer := buf'first;"),
VSTR("begin"),
VSTR(" while ( i <= max_size ) loop"),
VSTR(" if (end_of_line) then -- Ada ate our newline, put it back on the end."),
VSTR(" buf(loc) := ASCII.LF;"),
VSTR(" skip_line(1);"),
VSTR("%%"),
VSTR(" else"),
VSTR(" get(buf(loc));"),
VSTR(" end if; "),
VSTR(" "),
VSTR(" loc := loc + 1;"),
VSTR(" i := i + 1;"),
VSTR(" end loop;"),
VSTR(" "),
VSTR(" result := i - 1; "),
VSTR(" exception"),
VSTR(" when END_ERROR => result := i - 1;"),
VSTR(" -- when we hit EOF we need to set yy_eof_has_been_seen"),
VSTR(" yy_eof_has_been_seen := true;"),
VSTR("end YY_INPUT;"),
VSTR(""),
VSTR("-- yy_get_next_buffer - try to read in new buffer"),
VSTR("--"),
VSTR("-- returns a code representing an action"),
VSTR("-- EOB_ACT_LAST_MATCH - "),
VSTR("-- EOB_ACT_RESTART_SCAN - restart the scanner"),
VSTR("-- EOB_ACT_END_OF_FILE - end of file"),
VSTR(""),
VSTR("function yy_get_next_buffer return eob_action_type is"),
VSTR(" dest : integer := 0;"),
VSTR(" source : integer := yytext_ptr - 1; -- copy prev. char, too"),
VSTR(" number_to_move : integer;"),
VSTR(" ret_val : eob_action_type;"),
VSTR(" num_to_read : integer;"),
VSTR("begin "),
VSTR(" if ( yy_c_buf_p > yy_n_chars + 1 ) then"),
VSTR(" raise NULL_IN_INPUT;"),
VSTR(" end if;"),
VSTR(""),
VSTR(" -- try to read more data"),
VSTR(""),
VSTR(" -- first move last chars to start of buffer"),
VSTR(" number_to_move := yy_c_buf_p - yytext_ptr;"),
VSTR(""),
VSTR(" for i in 0..number_to_move - 1 loop"),
VSTR(" yy_ch_buf(dest) := yy_ch_buf(source);"),
VSTR(" dest := dest + 1;"),
VSTR(" source := source + 1;"),
VSTR(" end loop;"),
VSTR(" "),
VSTR(" if ( yy_eof_has_been_seen ) then"),
VSTR(" -- don't do the read, it's not guaranteed to return an EOF,"),
VSTR(" -- just force an EOF"),
VSTR(""),
VSTR(" yy_n_chars := 0;"),
VSTR(" else"),
VSTR(" num_to_read := YY_BUF_SIZE - number_to_move - 1;"),
VSTR(""),
VSTR(" if ( num_to_read > YY_READ_BUF_SIZE ) then"),
VSTR(" num_to_read := YY_READ_BUF_SIZE;"),
VSTR(" end if;"),
VSTR(""),
VSTR(" -- read in more data"),
VSTR(" YY_INPUT( yy_ch_buf(number_to_move..yy_ch_buf'last), yy_n_chars, num_to_read );"),
VSTR(" end if;"),
VSTR(" if ( yy_n_chars = 0 ) then"),
VSTR(" if ( number_to_move = 1 ) then"),
VSTR(" ret_val := EOB_ACT_END_OF_FILE;"),
VSTR(" else"),
VSTR(" ret_val := EOB_ACT_LAST_MATCH;"),
VSTR(" end if;"),
VSTR(""),
VSTR(" yy_eof_has_been_seen := true;"),
VSTR(" else"),
VSTR(" ret_val := EOB_ACT_RESTART_SCAN;"),
VSTR(" end if;"),
VSTR(" "),
VSTR(" yy_n_chars := yy_n_chars + number_to_move;"),
VSTR(" yy_ch_buf(yy_n_chars) := YY_END_OF_BUFFER_CHAR;"),
VSTR(" yy_ch_buf(yy_n_chars + 1) := YY_END_OF_BUFFER_CHAR;"),
VSTR(""),
VSTR(" -- yytext begins at the second character in"),
VSTR(" -- yy_ch_buf; the first character is the one which"),
VSTR(" -- preceded it before reading in the latest buffer;"),
VSTR(" -- it needs to be kept around in case it's a"),
VSTR(" -- newline, so yy_get_previous_state() will have"),
VSTR(" -- with '^' rules active"),
VSTR(""),
VSTR(" yytext_ptr := 1;"),
VSTR(""),
VSTR(" return ret_val;"),
VSTR("end yy_get_next_buffer;"),
VSTR(""),
VSTR("procedure yyunput( c : character; yy_bp: in out integer ) is"),
VSTR(" number_to_move : integer;"),
VSTR(" dest : integer;"),
VSTR(" source : integer;"),
VSTR(" tmp_yy_cp : integer;"),
VSTR("begin"),
VSTR(" tmp_yy_cp := yy_c_buf_p;"),
VSTR(" yy_ch_buf(tmp_yy_cp) := yy_hold_char; -- undo effects of setting up yytext"),
VSTR(""),
VSTR(" if ( tmp_yy_cp < 2 ) then"),
VSTR(" -- need to shift things up to make room"),
VSTR(" number_to_move := yy_n_chars + 2; -- +2 for EOB chars"),
VSTR(" dest := YY_BUF_SIZE + 2;"),
VSTR(" source := number_to_move;"),
VSTR(""),
VSTR(" while ( source > 0 ) loop"),
VSTR(" dest := dest - 1;"),
VSTR(" source := source - 1;"),
VSTR(" yy_ch_buf(dest) := yy_ch_buf(source);"),
VSTR(" end loop;"),
VSTR(""),
VSTR(" tmp_yy_cp := tmp_yy_cp + dest - source;"),
VSTR(" yy_bp := yy_bp + dest - source;"),
VSTR(" yy_n_chars := YY_BUF_SIZE;"),
VSTR(""),
VSTR(" if ( tmp_yy_cp < 2 ) then"),
VSTR(" raise PUSHBACK_OVERFLOW;"),
VSTR(" end if;"),
VSTR(" end if;"),
VSTR(""),
VSTR(" if ( tmp_yy_cp > yy_bp and then yy_ch_buf(tmp_yy_cp-1) = ASCII.LF ) then"),
VSTR(" yy_ch_buf(tmp_yy_cp-2) := ASCII.LF;"),
VSTR(" end if;"),
VSTR(""),
VSTR(" tmp_yy_cp := tmp_yy_cp - 1;"),
VSTR(" yy_ch_buf(tmp_yy_cp) := c;"),
VSTR(""),
VSTR("-- Note: this code is the text of YY_DO_BEFORE_ACTION, only"),
VSTR("-- here we get different yy_cp and yy_bp's"),
VSTR(" yytext_ptr := yy_bp;"),
VSTR(" yy_hold_char := yy_ch_buf(tmp_yy_cp);"),
VSTR(" yy_ch_buf(tmp_yy_cp) := ASCII.NUL;"),
VSTR(" yy_c_buf_p := tmp_yy_cp;"),
VSTR("end yyunput;"),
VSTR(""),
VSTR("procedure unput(c : character) is"),
VSTR("begin"),
VSTR(" yyunput( c, yy_bp );"),
VSTR("end unput;"),
VSTR(""),
VSTR("function input return character is"),
VSTR(" c : character;"),
VSTR(" yy_cp : integer := yy_c_buf_p;"),
VSTR("begin"),
VSTR(" yy_ch_buf(yy_cp) := yy_hold_char;"),
VSTR(""),
VSTR(" if ( yy_ch_buf(yy_c_buf_p) = YY_END_OF_BUFFER_CHAR ) then"),
VSTR(" -- need more input"),
VSTR(" yytext_ptr := yy_c_buf_p;"),
VSTR(" yy_c_buf_p := yy_c_buf_p + 1;"),
VSTR(""),
VSTR(" case yy_get_next_buffer is"),
VSTR(" -- this code, unfortunately, is somewhat redundant with"),
VSTR(" -- that above"),
VSTR(""),
VSTR(" when EOB_ACT_END_OF_FILE =>"),
VSTR(" if ( yywrap ) then"),
VSTR(" yy_c_buf_p := yytext_ptr;"),
VSTR(" return ASCII.NUL;"),
VSTR(" end if;"),
VSTR(""),
VSTR(" yy_ch_buf(0) := ASCII.LF;"),
VSTR(" yy_n_chars := 1;"),
VSTR(" yy_ch_buf(yy_n_chars) := YY_END_OF_BUFFER_CHAR;"),
VSTR(" yy_ch_buf(yy_n_chars + 1) := YY_END_OF_BUFFER_CHAR;"),
VSTR(" yy_eof_has_been_seen := false;"),
VSTR(" yy_c_buf_p := 1;"),
VSTR(" yytext_ptr := yy_c_buf_p;"),
VSTR(" yy_hold_char := yy_ch_buf(yy_c_buf_p);"),
VSTR(""),
VSTR(" return ( input );"),
VSTR(" when EOB_ACT_RESTART_SCAN =>"),
VSTR(" yy_c_buf_p := yytext_ptr;"),
VSTR(""),
VSTR(" when EOB_ACT_LAST_MATCH =>"),
VSTR(" raise UNEXPECTED_LAST_MATCH;"),
VSTR(" when others => null;"),
VSTR(" end case;"),
VSTR(" end if;"),
VSTR(""),
VSTR(" c := yy_ch_buf(yy_c_buf_p);"),
VSTR(" yy_c_buf_p := yy_c_buf_p + 1;"),
VSTR(" yy_hold_char := yy_ch_buf(yy_c_buf_p);"),
VSTR(""),
VSTR(" return c;"),
VSTR("end input;"),
VSTR(""),
VSTR("procedure output(c : character) is"),
VSTR("begin"),
VSTR(" text_io.put(c);"),
VSTR("end output;"),
VSTR(""),
VSTR("-- default yywrap function - always treat EOF as an EOF"),
VSTR("function yywrap return boolean is"),
VSTR("begin"),
VSTR(" return true;"),
VSTR("end yywrap;"),
VSTR(""),
VSTR("procedure Open_Input(fname : in String) is"),
VSTR(" f : file_type;"),
VSTR("begin"),
VSTR(" yy_init := true;"),
VSTR(" open(f, in_file, fname);"),
VSTR(" set_input(f);"),
VSTR("end Open_Input;"),
VSTR(""),
VSTR("procedure Create_Output(fname : in String := """") is"),
VSTR(" f : file_type;"),
VSTR("begin"),
VSTR(" if (fname /= """") then"),
VSTR(" create(f, out_file, fname);"),
VSTR(" set_output(f);"),
VSTR(" end if;"),
VSTR("end Create_Output;"),
VSTR(""),
VSTR("procedure Close_Input is"),
VSTR("begin"),
VSTR(" null;"),
VSTR("end Close_Input;"),
VSTR(""),
VSTR("procedure Close_Output is"),
VSTR("begin"),
VSTR(" null;"),
VSTR("end Close_Output;"),
VSTR("")
--IO TEMPLATE END
);
IO_CURRENT_LINE : INTEGER := 1;
procedure TEMPLATE_OUT(OUTFILE : in FILE_TYPE;
CURRENT_TEMPLATE : in FILE_ARRAY;
LINE_NUMBER : in out INTEGER) is
BUF : VSTRING;
begin
while (not (LINE_NUMBER > CURRENT_TEMPLATE'LAST)) loop
BUF := CURRENT_TEMPLATE(LINE_NUMBER);
LINE_NUMBER := LINE_NUMBER + 1;
if ((FILE_STRING.LEN(BUF) >= 2) and then ((CHAR(BUF, 1) = '%') and (CHAR(
BUF, 2) = '%'))) then
exit;
else
FILE_STRING.PUT_LINE(OUTFILE, BUF);
end if;
end loop;
end TEMPLATE_OUT;
procedure GENERATE_DFA_FILE is
DFA_OUT_FILE : FILE_TYPE;
begin
EXTERNAL_FILE_MANAGER.GET_DFA_FILE(DFA_OUT_FILE);
TEXT_IO.PUT_LINE(DFA_OUT_FILE, "package " & TSTRING.STR(MISC.BASENAME) &
"_dfa" & " is");
if (DDEBUG) then
-- make a scanner that output acceptance information
TEXT_IO.PUT_LINE(DFA_OUT_FILE, "aflex_debug : boolean := true;");
else
TEXT_IO.PUT_LINE(DFA_OUT_FILE, "aflex_debug : boolean := false;");
end if;
TEMPLATE_OUT(DFA_OUT_FILE, DFA_TEMPLATE, DFA_CURRENT_LINE);
TEXT_IO.PUT_LINE(DFA_OUT_FILE, "end " & TSTRING.STR(MISC.BASENAME) & "_dfa;"
);
TEXT_IO.NEW_LINE(DFA_OUT_FILE);
TEXT_IO.PUT(DFA_OUT_FILE, "with " & TSTRING.STR(MISC.BASENAME) & "_dfa" &
"; ");
TEXT_IO.PUT_LINE(DFA_OUT_FILE, "use " & TSTRING.STR(MISC.BASENAME) & "_dfa"
& "; ");
TEXT_IO.PUT_LINE(DFA_OUT_FILE, "package body " & TSTRING.STR(MISC.BASENAME)
& "_dfa" & " is");
TEMPLATE_OUT(DFA_OUT_FILE, DFA_TEMPLATE, DFA_CURRENT_LINE);
TEXT_IO.PUT_LINE(DFA_OUT_FILE, "end " & TSTRING.STR(MISC.BASENAME) & "_dfa;"
);
end GENERATE_DFA_FILE;
procedure GENERATE_IO_FILE is
IO_OUT_FILE : FILE_TYPE;
begin
EXTERNAL_FILE_MANAGER.GET_IO_FILE(IO_OUT_FILE);
TEXT_IO.PUT(IO_OUT_FILE, "with " & TSTRING.STR(MISC.BASENAME) & "_dfa" &
"; ");
TEXT_IO.PUT_LINE(IO_OUT_FILE, "use " & TSTRING.STR(MISC.BASENAME) & "_dfa"
& "; ");
TEMPLATE_OUT(IO_OUT_FILE, IO_TEMPLATE, IO_CURRENT_LINE);
TEXT_IO.PUT_LINE(IO_OUT_FILE, "package " & TSTRING.STR(MISC.BASENAME) &
"_io" & " is");
TEMPLATE_OUT(IO_OUT_FILE, IO_TEMPLATE, IO_CURRENT_LINE);
TEXT_IO.PUT_LINE(IO_OUT_FILE, "end " & TSTRING.STR(MISC.BASENAME) & "_io;")
;
TEXT_IO.NEW_LINE(IO_OUT_FILE);
TEXT_IO.PUT_LINE(IO_OUT_FILE, "package body " & TSTRING.STR(MISC.BASENAME)
& "_io" & " is");
TEMPLATE_OUT(IO_OUT_FILE, IO_TEMPLATE, IO_CURRENT_LINE);
-- If we're generating a scanner for interactive mode we need to generate
-- a YY_INPUT that stops at the end of each line
if INTERACTIVE then
TEXT_IO.PUT_LINE(IO_OUT_FILE,
" i := i + 1; -- update counter, miss end of loop");
TEXT_IO.PUT_LINE(IO_OUT_FILE,
" exit; -- in interactive mode return at end of line.");
end if;
TEMPLATE_OUT(IO_OUT_FILE, IO_TEMPLATE, IO_CURRENT_LINE);
TEXT_IO.PUT_LINE(IO_OUT_FILE, "end " & TSTRING.STR(MISC.BASENAME) & "_io;")
;
end GENERATE_IO_FILE;
end TEMPLATE_MANAGER;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE template manager
-- AUTHOR: John Self (UCI)
-- DESCRIPTION supports output of internalized templates for the IO and DFA
-- packages.
-- NOTES This package is quite a memory hog, and is really only useful on
-- virtual memory systems. It could use an external file to store the
-- templates like the skeleton manager. This would save memory at the
-- cost of a slight reduction in speed and the necessity of keeping
-- copies of the template files in a known place.
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/template_managerS.a,v 1.3 90/01/12 15:20:49 self Exp Locker: self $
package TEMPLATE_MANAGER is
procedure GENERATE_DFA_FILE;
procedure GENERATE_IO_FILE;
end TEMPLATE_MANAGER;
-- Copyright (c) 1990 Regents of the University of California.
-- All rights reserved.
--
-- This software was developed by John Self of the Arcadia project
-- at the University of California, Irvine.
--
-- 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.
-- TITLE variable length strings
-- AUTHOR: John Self (UCI)
-- DESCRIPTION these strings are used for many functions
-- $Header: /co/ua/self/arcadia/aflex/ada/src/RCS/tstrings.a,v 1.4 90/01/12 15:20:51 self Exp Locker: self $
with VSTRINGS;
package TSTRING is
new VSTRINGS(1024); -- This is MAXLINE in misc_defs
-- UNIT: generic package body of VSTRINGS
--
-- FILES: vstring_body.a in publiclib
-- related file is vstring_spec.a in publiclib
--
-- PURPOSE: An implementation of the abstract data type "variable-length
-- string."
--
-- DESCRIPTION: This package provides a private type VSTRING. VSTRING objects
-- are "strings" that have a length between zero and LAST, where
-- LAST is the generic parameter supplied in the package
-- instantiation.
--
-- In addition to the type VSTRING, a subtype and two constants
-- are declared. The subtype STRINDEX is an index to a VSTRING,
-- The STRINDEX constant FIRST is an index to the first character
-- of the string, and the VSTRING constant NUL is a VSTRING of
-- length zero. NUL is the default initial value of a VSTRING.
--
-- The following sets of functions, procedures, and operators
-- are provided as operations on the type VSTRING:
--
-- ATTRIBUTE FUNCTIONS: LEN, MAX, STR, CHAR
-- The attribute functions return the characteristics of
-- a VSTRING.
--
-- COMPARISON OPERATORS: "=", "/=", "<", ">", "<=", ">="
-- The comparison operators are the same as for the predefined
-- type STRING.
--
-- INPUT/OUTPUT PROCEDURES: GET, GET_LINE, PUT, PUT_LINE
--
-- The input/output procedures are similar to those for the
-- predefined type STRING, with the following exceptions:
--
-- - GET has an optional parameter LENGTH, which indicates
-- the number of characters to get (default is LAST).
--
-- - GET_LINE does not have a parameter to return the length
-- of the string (the LEN function should be used instead).
--
-- EXTRACTION FUNCTIONS: SLICE, SUBSTR, DELETE
-- The SLICE function returns the slice of a VSTRING between
-- two indices (equivalent to STR(X)(A .. B)).
--
-- SUBSTR returns a substring of a VSTRING taken from a given
-- index and extending a given length.
--
-- The DELETE function returns the VSTRING which results from
-- removing the slice between two indices.
--
-- EDITING FUNCTIONS: INSERT, APPEND, REPLACE
-- The editing functions return the VSTRING which results from
-- inserting, appending, or replacing at a given index with a
-- VSTRING, STRING, or CHARACTER. The index must be in the
-- current range of the VSTRING; i.e., zero cannot be used.
--
-- CONCATENATION OPERATOR: "&"
-- The concatenation operator is the same as for the type
-- STRING. It should be used instead of APPEND when the
-- APPEND would always be after the last character.
--
-- POSITION FUNCTIONS: INDEX, RINDEX
-- The position functions return an index to the Nth occurrence
-- of a VSTRING, STRING, or CHARACTER from the front or back
-- of a VSTRING. Zero is returned if the search is not
-- successful.
--
-- CONVERSION FUNCTIONS AND OPERATOR: VSTR, CONVERT, "+"
-- VSTR converts a STRING or a CHARACTER to a VSTRING.
--
-- CONVERT is a generic function which can be instantiated to
-- convert from any given variable-length string to another,
-- provided the FROM type has a function equivelent to STR
-- defined for it, and that the TO type has a function equiv-
-- elent to VSTR defined for it. This provides a means for
-- converting between VSTRINGs declared in separate instant-
-- iations of VSTRINGS. When instantiating CONVERT for
-- VSTRINGs, the STR and VSTR functions are implicitly defined,
-- provided that they have been made visible (by a use clause).
--
-- Note: CONVERT is NOT implicitly associated with the type
-- VSTRING declared in this package (since it would not be a
-- derivable function (see RM 3.4(11))).
--
-- Caution: CONVERT cannot be instantiated directly with the
-- names VSTR and STR, since the name of the subprogram being
-- declared would hide the generic parameters with the same
-- names (see RM 8.3(16)). CONVERT can be instantiated with
-- the operator "+", and any instantiation of CONVERT can
-- subsequently be renamed VSTR or STR.
--
-- Example: Given two VSTRINGS instantiations X and Y:
-- function "+" is new X.CONVERT(X.VSTRING, Y.VSTRING);
-- function "+" is new X.CONVERT(Y.VSTRING, X.VSTRING);
--
-- (Y.CONVERT could have been used in place of X.CONVERT)
--
-- function VSTR(A : X.VSTRING) return Y.VSTRING renames "+";
-- function VSTR(A : Y.VSTRING) return X.VSTRING renames "+";
--
-- "+" is equivelent to VSTR. It is supplied as a short-hand
-- notation for the function. The "+" operator cannot immed-
-- iately follow the "&" operator; use ... & (+ ...) instead.
pragma PAGE;
\f
-- DISCUSSION:
--
-- This package implements the type "variable-length string" (vstring)
-- using generics. The alternative approaches are to use a discriminant
-- record in which the discriminant controls the length of a STRING inside
-- the record, or a record containing an access type which points to a
-- string, which can be deallocated and reallocated when necessary.
--
-- Advantages of this package:
-- * The other approaches force the vstring to be a limited private
-- type. Thus, their vstrings cannot appear on the left side of
-- the assignment operator; ie., their vstrings cannot be given
-- initial values or values by direct assignment. This package
-- uses a private type; therefore, these things can be done.
--
-- * The other approach stores the vstring in a string whose length
-- is determined dynamically. This package uses a fixed length
-- string. This difference might be reflected in faster and more
-- consistent execution times (this has NOT been verified).
--
-- Disadvantages of this package:
-- * Different instantiations must be used to declare vstrings with
-- different maximum lengths (this may be desirable, since
-- CONSTRAINT_ERROR will be raised if the maximum is exceeded).
--
-- * A second declaration is required to give the type declared by
-- the instantiation a name other than "VSTRING."
--
-- * The storage required for a vstring is determined by the generic
-- parameter LAST and not the actual length of its contents. Thus,
-- each object is allocated the maximum amount of storage, regardless
-- of its actual size.
--
-- MISCELLANEOUS:
-- Constraint checking is done explicitly in the code; thus, it cannot
-- be suppressed. On the other hand, constraint checking is not lost
-- if pragma suppress is supplied to the compilation (-S option)
-- (The robustness of the explicit constraint checking has NOT been
-- determined).
--
-- Compiling with the optimizer (-O option) may significantly reduce
-- the size (and possibly execution time) of the resulting executable.
--
-- Compiling an instantiation of VSTRINGS is roughly equivelent to
-- recompiling VSTRINGS. Since this takes a significant amount of time,
-- and the instantiation does not depend on any other library units,
-- it is STRONGLY recommended that the instantiation be compiled
-- separately, and thus done only ONCE.
--
-- USAGE: with VSTRINGS;
-- package package_name is new VSTRINGS(maximum_length);
-- .......................................................................... --
pragma PAGE;
\f
package body VSTRINGS is
-- local declarations
FILL_CHAR : constant CHARACTER := ASCII.NUL;
procedure FORMAT(THE_STRING : in out VSTRING; OLDLEN : in STRINDEX := LAST) is
-- fill the string with FILL_CHAR to null out old values
begin -- FORMAT (Local Procedure)
THE_STRING.VALUE(THE_STRING.LEN + 1 .. OLDLEN) :=
(others => FILL_CHAR);
end FORMAT;
-- bodies of visible operations
function LEN(FROM : VSTRING) return STRINDEX is
begin -- LEN
return(FROM.LEN);
end LEN;
function MAX(FROM : VSTRING) return STRINDEX is
begin -- MAX
return(LAST);
end MAX;
function STR(FROM : VSTRING) return STRING is
begin -- STR
return(FROM.VALUE(FIRST .. FROM.LEN));
end STR;
function CHAR(FROM : VSTRING; POSITION : STRINDEX := FIRST)
return CHARACTER is
begin -- CHAR
if POSITION not in FIRST .. FROM.LEN
then raise CONSTRAINT_ERROR;
end if;
return(FROM.VALUE(POSITION));
end CHAR;
function "<" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN is
begin -- "<"
return(LEFT.VALUE < RIGHT.VALUE);
end "<";
function ">" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN is
begin -- ">"
return(LEFT.VALUE > RIGHT.VALUE);
end ">";
function "<=" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN is
begin -- "<="
return(LEFT.VALUE <= RIGHT.VALUE);
end "<=";
function ">=" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN is
begin -- ">="
return(LEFT.VALUE >= RIGHT.VALUE);
end ">=";
procedure PUT(FILE : in FILE_TYPE; ITEM : in VSTRING) is
begin -- PUT
PUT(FILE, ITEM.VALUE(FIRST .. ITEM.LEN));
end PUT;
procedure Put(ITEM : in VSTRING) is
begin -- PUT
PUT(ITEM.VALUE(FIRST .. ITEM.LEN));
end PUT;
procedure PUT_LINE(FILE : in FILE_TYPE; ITEM : in VSTRING) is
begin -- PUT_LINE
PUT_LINE(FILE, ITEM.VALUE(FIRST .. ITEM.LEN));
end PUT_LINE;
procedure PUT_LINE(ITEM : in VSTRING) is
begin -- PUT_LINE
PUT_LINE(ITEM.VALUE(FIRST .. ITEM.LEN));
end PUT_LINE;
procedure GET(FILE : in FILE_TYPE; ITEM : out VSTRING;
LENGTH : in STRINDEX := LAST) is
begin -- GET
if LENGTH not in FIRST .. LAST
then raise CONSTRAINT_ERROR;
end if;
ITEM := NUL;
for INDEX in FIRST .. LENGTH loop
GET(FILE, ITEM.VALUE(INDEX));
ITEM.LEN := INDEX;
end loop;
end GET;
procedure GET(ITEM : out VSTRING; LENGTH : in STRINDEX := LAST) is
begin -- GET
if LENGTH not in FIRST .. LAST
then raise CONSTRAINT_ERROR;
end if;
ITEM := NUL;
for INDEX in FIRST .. LENGTH loop
GET(ITEM.VALUE(INDEX));
ITEM.LEN := INDEX;
end loop;
end GET;
procedure GET_LINE(FILE : in FILE_TYPE; ITEM : in out VSTRING) is
OLDLEN : constant STRINDEX := ITEM.LEN;
begin -- GET_LINE
GET_LINE(FILE, ITEM.VALUE, ITEM.LEN);
FORMAT(ITEM, OLDLEN);
end GET_LINE;
procedure GET_LINE(ITEM : in out VSTRING) is
OLDLEN : constant STRINDEX := ITEM.LEN;
begin -- GET_LINE
GET_LINE(ITEM.VALUE, ITEM.LEN);
FORMAT(ITEM, OLDLEN);
end GET_LINE;
function SLICE(FROM : VSTRING; FRONT, BACK : STRINDEX) return VSTRING is
begin -- SLICE
if ((FRONT not in FIRST .. FROM.LEN) or else
(BACK not in FIRST .. FROM.LEN)) and then FRONT <= BACK
then raise CONSTRAINT_ERROR;
end if;
return(Vstr(FROM.VALUE(FRONT .. BACK)));
end SLICE;
function SUBSTR(FROM : VSTRING; START, LENGTH : STRINDEX) return VSTRING is
begin -- SUBSTR
if (START not in FIRST .. FROM.LEN) or else
((START + LENGTH - 1 not in FIRST .. FROM.LEN)
and then (LENGTH > 0))
then raise CONSTRAINT_ERROR;
end if;
return(Vstr(FROM.VALUE(START .. START + LENGTH -1)));
end SUBSTR;
function DELETE(FROM : VSTRING; FRONT, BACK : STRINDEX) return VSTRING is
TEMP : VSTRING := FROM;
begin -- DELETE
if ((FRONT not in FIRST .. FROM.LEN) or else
(BACK not in FIRST .. FROM.LEN)) and then FRONT <= BACK
then raise CONSTRAINT_ERROR;
end if;
if FRONT > BACK then return(FROM); end if;
TEMP.LEN := FROM.LEN - (BACK - FRONT) - 1;
TEMP.VALUE(FRONT .. TEMP.LEN) := FROM.VALUE(BACK + 1 .. FROM.LEN);
FORMAT(TEMP, FROM.LEN);
return(TEMP);
end DELETE;
function INSERT(TARGET: VSTRING; ITEM: VSTRING;
POSITION : STRINDEX := FIRST) return VSTRING is
TEMP : VSTRING;
begin -- INSERT
if POSITION not in FIRST .. TARGET.LEN
then raise CONSTRAINT_ERROR;
end if;
if TARGET.LEN + ITEM.LEN > LAST
then raise CONSTRAINT_ERROR;
else TEMP.LEN := TARGET.LEN + ITEM.LEN;
end if;
TEMP.VALUE(FIRST .. POSITION - 1) := TARGET.VALUE(FIRST .. POSITION - 1);
TEMP.VALUE(POSITION .. (POSITION + ITEM.LEN - 1)) :=
ITEM.VALUE(FIRST .. ITEM.LEN);
TEMP.VALUE((POSITION + ITEM.LEN) .. TEMP.LEN) :=
TARGET.VALUE(POSITION .. TARGET.LEN);
return(TEMP);
end INSERT;
function INSERT(TARGET: VSTRING; ITEM: STRING;
POSITION : STRINDEX := FIRST) return VSTRING is
begin -- INSERT
return INSERT(TARGET, VSTR(ITEM), POSITION);
end INSERT;
function INSERT(TARGET: VSTRING; ITEM: CHARACTER;
POSITION : STRINDEX := FIRST) return VSTRING is
begin -- INSERT
return INSERT(TARGET, VSTR(ITEM), POSITION);
end INSERT;
function APPEND(TARGET: VSTRING; ITEM: VSTRING; POSITION : STRINDEX)
return VSTRING is
TEMP : VSTRING;
POS : STRINDEX := POSITION;
begin -- APPEND
if POSITION not in FIRST .. TARGET.LEN
then raise CONSTRAINT_ERROR;
end if;
if TARGET.LEN + ITEM.LEN > LAST
then raise CONSTRAINT_ERROR;
else TEMP.LEN := TARGET.LEN + ITEM.LEN;
end if;
TEMP.VALUE(FIRST .. POS) := TARGET.VALUE(FIRST .. POS);
TEMP.VALUE(POS + 1 .. (POS + ITEM.LEN)) := ITEM.VALUE(FIRST .. ITEM.LEN);
TEMP.VALUE((POS + ITEM.LEN + 1) .. TEMP.LEN) :=
TARGET.VALUE(POS + 1 .. TARGET.LEN);
return(TEMP);
end APPEND;
function APPEND(TARGET: VSTRING; ITEM: STRING; POSITION : STRINDEX)
return VSTRING is
begin -- APPEND
return APPEND(TARGET, VSTR(ITEM), POSITION);
end APPEND;
function APPEND(TARGET: VSTRING; ITEM: CHARACTER; POSITION : STRINDEX)
return VSTRING is
begin -- APPEND
return APPEND(TARGET, VSTR(ITEM), POSITION);
end APPEND;
function APPEND(TARGET: VSTRING; ITEM: VSTRING) return VSTRING is
begin -- APPEND
return(APPEND(TARGET, ITEM, TARGET.LEN));
end APPEND;
function APPEND(TARGET: VSTRING; ITEM: STRING) return VSTRING is
begin -- APPEND
return(APPEND(TARGET, VSTR(ITEM), TARGET.LEN));
end APPEND;
function APPEND(TARGET: VSTRING; ITEM: CHARACTER) return VSTRING is
begin -- APPEND
return(APPEND(TARGET, VSTR(ITEM), TARGET.LEN));
end APPEND;
function REPLACE(TARGET: VSTRING; ITEM: VSTRING;
POSITION : STRINDEX := FIRST) return VSTRING is
TEMP : VSTRING;
begin -- REPLACE
if POSITION not in FIRST .. TARGET.LEN
then raise CONSTRAINT_ERROR;
end if;
if POSITION + ITEM.LEN - 1 <= TARGET.LEN
then TEMP.LEN := TARGET.LEN;
elsif POSITION + ITEM.LEN - 1 > LAST
then raise CONSTRAINT_ERROR;
else TEMP.LEN := POSITION + ITEM.LEN - 1;
end if;
TEMP.VALUE(FIRST .. POSITION - 1) := TARGET.VALUE(FIRST .. POSITION - 1);
TEMP.VALUE(POSITION .. (POSITION + ITEM.LEN - 1)) :=
ITEM.VALUE(FIRST .. ITEM.LEN);
TEMP.VALUE((POSITION + ITEM.LEN) .. TEMP.LEN) :=
TARGET.VALUE((POSITION + ITEM.LEN) .. TARGET.LEN);
return(TEMP);
end REPLACE;
function REPLACE(TARGET: VSTRING; ITEM: STRING;
POSITION : STRINDEX := FIRST) return VSTRING is
begin -- REPLACE
return REPLACE(TARGET, VSTR(ITEM), POSITION);
end REPLACE;
function REPLACE(TARGET: VSTRING; ITEM: CHARACTER;
POSITION : STRINDEX := FIRST) return VSTRING is
begin -- REPLACE
return REPLACE(TARGET, VSTR(ITEM), POSITION);
end REPLACE;
function "&"(LEFT:VSTRING; RIGHT : VSTRING) return VSTRING is
TEMP : VSTRING;
begin -- "&"
if LEFT.LEN + RIGHT.LEN > LAST
then raise CONSTRAINT_ERROR;
else TEMP.LEN := LEFT.LEN + RIGHT.LEN;
end if;
TEMP.VALUE(FIRST .. TEMP.LEN) := LEFT.VALUE(FIRST .. LEFT.LEN) &
RIGHT.VALUE(FIRST .. RIGHT.LEN);
return(TEMP);
end "&";
function "&"(LEFT:VSTRING; RIGHT : STRING) return VSTRING is
begin -- "&"
return LEFT & VSTR(RIGHT);
end "&";
function "&"(LEFT:VSTRING; RIGHT : CHARACTER) return VSTRING is
begin -- "&"
return LEFT & VSTR(RIGHT);
end "&";
function "&"(LEFT : STRING; RIGHT : VSTRING) return VSTRING is
begin -- "&"
return VSTR(LEFT) & RIGHT;
end "&";
function "&"(LEFT : CHARACTER; RIGHT : VSTRING) return VSTRING is
begin -- "&"
return VSTR(LEFT) & RIGHT;
end "&";
Function INDEX(WHOLE : VSTRING; PART : VSTRING; OCCURRENCE : NATURAL := 1)
return STRINDEX is
NOT_FOUND : constant NATURAL := 0;
INDEX : NATURAL := FIRST;
COUNT : NATURAL := 0;
begin -- INDEX
if PART = NUL then return(NOT_FOUND); -- by definition
end if;
while INDEX + PART.LEN - 1 <= WHOLE.LEN and then COUNT < OCCURRENCE loop
if WHOLE.VALUE(INDEX .. PART.LEN + INDEX - 1) =
PART.VALUE(1 .. PART.LEN)
then COUNT := COUNT + 1;
end if;
INDEX := INDEX + 1;
end loop;
if COUNT = OCCURRENCE
then return(INDEX - 1);
else return(NOT_FOUND);
end if;
end INDEX;
Function INDEX(WHOLE : VSTRING; PART : STRING; OCCURRENCE : NATURAL := 1)
return STRINDEX is
begin -- Index
return(Index(WHOLE, VSTR(PART), OCCURRENCE));
end INDEX;
Function INDEX(WHOLE : VSTRING; PART : CHARACTER; OCCURRENCE : NATURAL := 1)
return STRINDEX is
begin -- Index
return(Index(WHOLE, VSTR(PART), OCCURRENCE));
end INDEX;
function RINDEX(WHOLE: VSTRING; PART:VSTRING; OCCURRENCE:NATURAL := 1)
return STRINDEX is
NOT_FOUND : constant NATURAL := 0;
INDEX : INTEGER := WHOLE.LEN - (PART.LEN -1);
COUNT : NATURAL := 0;
begin -- RINDEX
if PART = NUL then return(NOT_FOUND); -- by definition
end if;
while INDEX >= FIRST and then COUNT < OCCURRENCE loop
if WHOLE.VALUE(INDEX .. PART.LEN + INDEX - 1) =
PART.VALUE(1 .. PART.LEN)
then COUNT := COUNT + 1;
end if;
INDEX := INDEX - 1;
end loop;
if COUNT = OCCURRENCE
then
if COUNT > 0
then return(INDEX + 1);
else return(NOT_FOUND);
end if;
else return(NOT_FOUND);
end if;
end RINDEX;
Function RINDEX(WHOLE : VSTRING; PART : STRING; OCCURRENCE : NATURAL := 1)
return STRINDEX is
begin -- Rindex
return(RINDEX(WHOLE, VSTR(PART), OCCURRENCE));
end RINDEX;
Function RINDEX(WHOLE : VSTRING; PART : CHARACTER; OCCURRENCE : NATURAL := 1)
return STRINDEX is
begin -- Rindex
return(RINDEX(WHOLE, VSTR(PART), OCCURRENCE));
end RINDEX;
function VSTR(FROM : CHARACTER) return VSTRING is
TEMP : VSTRING;
begin -- VSTR
if LAST < 1
then raise CONSTRAINT_ERROR;
else TEMP.LEN := 1;
end if;
TEMP.VALUE(FIRST) := FROM;
return(TEMP);
end VSTR;
function VSTR(FROM : STRING) return VSTRING is
TEMP : VSTRING;
begin -- VSTR
if FROM'LENGTH > LAST
then raise CONSTRAINT_ERROR;
else TEMP.LEN := FROM'LENGTH;
end if;
TEMP.VALUE(FIRST .. FROM'LENGTH) := FROM;
return(TEMP);
end VSTR;
Function "+" (FROM : STRING) return VSTRING is
begin -- "+"
return(VSTR(FROM));
end "+";
Function "+" (FROM : CHARACTER) return VSTRING is
begin
return(VSTR(FROM));
end "+";
function CONVERT(X : FROM) return TO is
begin -- CONVERT
return(VSTR(STR(X)));
end CONVERT;
end VSTRINGS;
-- .......................................................................... --
--
-- DISTRIBUTION AND COPYRIGHT:
--
-- This software is released to the Public Domain (note:
-- software released to the Public Domain is not subject
-- to copyright protection).
-- Restrictions on use or distribution: NONE
--
-- DISCLAIMER:
--
-- This software and its documentation are provided "AS IS" and
-- without any expressed or implied warranties whatsoever.
-- No warranties as to performance, merchantability, or fitness
-- for a particular purpose exist.
--
-- Because of the diversity of conditions and hardware under
-- which this software may be used, no warranty of fitness for
-- a particular purpose is offered. The user is advised to
-- test the software thoroughly before relying on it. The user
-- must assume the entire risk and liability of using this
-- software.
--
-- In no event shall any person or organization of people be
-- held responsible for any direct, indirect, consequential
-- or inconsequential damages or lost profits.
-- UNIT: generic package spec of VSTRINGS
--
-- FILES: vstring_spec.a in publiclib
-- related file is vstring_body.a in publiclib
--
-- PURPOSE: An implementation of the abstract data type "variable-length
-- string."
--
-- DESCRIPTION: This package provides a private type VSTRING. VSTRING objects
-- are "strings" that have a length between zero and LAST, where
-- LAST is the generic parameter supplied in the package
-- instantiation.
--
-- In addition to the type VSTRING, a subtype and two constants
-- are declared. The subtype STRINDEX is an index to a VSTRING,
-- The STRINDEX constant FIRST is an index to the first character
-- of the string, and the VSTRING constant NUL is a VSTRING of
-- length zero. NUL is the default initial value of a VSTRING.
--
-- The following sets of functions, procedures, and operators
-- are provided as operations on the type VSTRING:
--
-- ATTRIBUTE FUNCTIONS: LEN, MAX, STR, CHAR
-- The attribute functions return the characteristics of
-- a VSTRING.
--
-- COMPARISON OPERATORS: "=", "/=", "<", ">", "<=", ">="
-- The comparison operators are the same as for the predefined
-- type STRING.
--
-- INPUT/OUTPUT PROCEDURES: GET, GET_LINE, PUT, PUT_LINE
--
-- The input/output procedures are similar to those for the
-- predefined type STRING, with the following exceptions:
--
-- - GET has an optional parameter LENGTH, which indicates
-- the number of characters to get (default is LAST).
--
-- - GET_LINE does not have a parameter to return the length
-- of the string (the LEN function should be used instead).
--
-- EXTRACTION FUNCTIONS: SLICE, SUBSTR, DELETE
-- The SLICE function returns the slice of a VSTRING between
-- two indices (equivalent to STR(X)(A .. B)).
--
-- SUBSTR returns a substring of a VSTRING taken from a given
-- index and extending a given length.
--
-- The DELETE function returns the VSTRING which results from
-- removing the slice between two indices.
--
-- EDITING FUNCTIONS: INSERT, APPEND, REPLACE
-- The editing functions return the VSTRING which results from
-- inserting, appending, or replacing at a given index with a
-- VSTRING, STRING, or CHARACTER. The index must be in the
-- current range of the VSTRING; i.e., zero cannot be used.
--
-- CONCATENATION OPERATOR: "&"
-- The concatenation operator is the same as for the type
-- STRING. It should be used instead of APPEND when the
-- APPEND would always be after the last character.
--
-- POSITION FUNCTIONS: INDEX, RINDEX
-- The position functions return an index to the Nth occurrence
-- of a VSTRING, STRING, or CHARACTER from the front or back
-- of a VSTRING. Zero is returned if the search is not
-- successful.
--
-- CONVERSION FUNCTIONS AND OPERATOR: VSTR, CONVERT, "+"
-- VSTR converts a STRING or a CHARACTER to a VSTRING.
--
-- CONVERT is a generic function which can be instantiated to
-- convert from any given variable-length string to another,
-- provided the FROM type has a function equivelent to STR
-- defined for it, and that the TO type has a function equiv-
-- elent to VSTR defined for it. This provides a means for
-- converting between VSTRINGs declared in separate instant-
-- iations of VSTRINGS. When instantiating CONVERT for
-- VSTRINGs, the STR and VSTR functions are implicitly defined,
-- provided that they have been made visible (by a use clause).
--
-- Note: CONVERT is NOT implicitly associated with the type
-- VSTRING declared in this package (since it would not be a
-- derivable function (see RM 3.4(11))).
--
-- Caution: CONVERT cannot be instantiated directly with the
-- names VSTR and STR, since the name of the subprogram being
-- declared would hide the generic parameters with the same
-- names (see RM 8.3(16)). CONVERT can be instantiated with
-- the operator "+", and any instantiation of CONVERT can
-- subsequently be renamed VSTR or STR.
--
-- Example: Given two VSTRINGS instantiations X and Y:
-- function "+" is new X.CONVERT(X.VSTRING, Y.VSTRING);
-- function "+" is new X.CONVERT(Y.VSTRING, X.VSTRING);
--
-- (Y.CONVERT could have been used in place of X.CONVERT)
--
-- function VSTR(A : X.VSTRING) return Y.VSTRING renames "+";
-- function VSTR(A : Y.VSTRING) return X.VSTRING renames "+";
--
-- "+" is equivelent to VSTR. It is supplied as a short-hand
-- notation for the function. The "+" operator cannot immed-
-- iately follow the "&" operator; use ... & (+ ...) instead.
pragma PAGE;
\f
-- DISCUSSION:
--
-- This package implements the type "variable-length string" (vstring)
-- using generics. The alternative approaches are to use a discriminant
-- record in which the discriminant controls the length of a STRING inside
-- the record, or a record containing an access type which points to a
-- string, which can be deallocated and reallocated when necessary.
--
-- Advantages of this package:
-- * The other approaches force the vstring to be a limited private
-- type. Thus, their vstrings cannot appear on the left side of
-- the assignment operator; ie., their vstrings cannot be given
-- initial values or values by direct assignment. This package
-- uses a private type; therefore, these things can be done.
--
-- * The other approach stores the vstring in a string whose length
-- is determined dynamically. This package uses a fixed length
-- string. This difference might be reflected in faster and more
-- consistent execution times (this has NOT been verified).
--
-- Disadvantages of this package:
-- * Different instantiations must be used to declare vstrings with
-- different maximum lengths (this may be desirable, since
-- CONSTRAINT_ERROR will be raised if the maximum is exceeded).
--
-- * A second declaration is required to give the type declared by
-- the instantiation a name other than "VSTRING."
--
-- * The storage required for a vstring is determined by the generic
-- parameter LAST and not the actual length of its contents. Thus,
-- each object is allocated the maximum amount of storage, regardless
-- of its actual size.
--
-- MISCELLANEOUS:
-- Constraint checking is done explicitly in the code; thus, it cannot
-- be suppressed. On the other hand, constraint checking is not lost
-- if pragma suppress is supplied to the compilation (-S option)
-- (The robustness of the explicit constraint checking has NOT been
-- determined).
--
-- Compiling with the optimizer (-O option) may significantly reduce
-- the size (and possibly execution time) of the resulting executable.
--
-- Compiling an instantiation of VSTRINGS is roughly equivelent to
-- recompiling VSTRINGS. Since this takes a significant amount of time,
-- and the instantiation does not depend on any other library units,
-- it is STRONGLY recommended that the instantiation be compiled
-- separately, and thus done only ONCE.
--
-- USAGE: with VSTRINGS;
-- package package_name is new VSTRINGS(maximum_length);
-- .......................................................................... --
pragma PAGE;
\f
with TEXT_IO; use TEXT_IO;
generic
LAST : NATURAL;
package VSTRINGS is
subtype STRINDEX is NATURAL;
FIRST : constant STRINDEX := STRINDEX'FIRST + 1;
type VSTRING is private;
NUL : constant VSTRING;
-- Attributes of a VSTRING
function LEN(FROM : VSTRING) return STRINDEX;
function MAX(FROM : VSTRING) return STRINDEX;
function STR(FROM : VSTRING) return STRING;
function CHAR(FROM: VSTRING; POSITION : STRINDEX := FIRST)
return CHARACTER;
-- Comparisons
function "<" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN;
function ">" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN;
function "<=" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN;
function ">=" (LEFT: VSTRING; RIGHT: VSTRING) return BOOLEAN;
-- "=" and "/=" are predefined
-- Input/Output
procedure PUT(FILE : in FILE_TYPE; ITEM : in VSTRING);
procedure PUT(ITEM : in VSTRING);
procedure PUT_LINE(FILE : in FILE_TYPE; ITEM : in VSTRING);
procedure PUT_LINE(ITEM : in VSTRING);
procedure GET(FILE : in FILE_TYPE; ITEM : out VSTRING;
LENGTH : in STRINDEX := LAST);
procedure GET(ITEM : out VSTRING; LENGTH : in STRINDEX := LAST);
procedure GET_LINE(FILE : in FILE_TYPE; ITEM : in out VSTRING);
procedure GET_LINE(ITEM : in out VSTRING);
-- Extraction
function SLICE(FROM: VSTRING; FRONT, BACK : STRINDEX) return VSTRING;
function SUBSTR(FROM: VSTRING; START, LENGTH: STRINDEX) return VSTRING;
function DELETE(FROM: VSTRING; FRONT, BACK : STRINDEX) return VSTRING;
-- Editing
function INSERT(TARGET: VSTRING; ITEM: VSTRING;
POSITION: STRINDEX := FIRST) return VSTRING;
function INSERT(TARGET: VSTRING; ITEM: STRING;
POSITION: STRINDEX := FIRST) return VSTRING;
function INSERT(TARGET: VSTRING; ITEM: CHARACTER;
POSITION: STRINDEX := FIRST) return VSTRING;
function APPEND(TARGET: VSTRING; ITEM: VSTRING; POSITION: STRINDEX)
return VSTRING;
function APPEND(TARGET: VSTRING; ITEM: STRING; POSITION: STRINDEX)
return VSTRING;
function APPEND(TARGET: VSTRING; ITEM: CHARACTER; POSITION: STRINDEX)
return VSTRING;
function APPEND(TARGET: VSTRING; ITEM: VSTRING) return VSTRING;
function APPEND(TARGET: VSTRING; ITEM: STRING) return VSTRING;
function APPEND(TARGET: VSTRING; ITEM: CHARACTER) return VSTRING;
function REPLACE(TARGET: VSTRING; ITEM: VSTRING;
POSITION: STRINDEX := FIRST) return VSTRING;
function REPLACE(TARGET: VSTRING; ITEM: STRING;
POSITION: STRINDEX := FIRST) return VSTRING;
function REPLACE(TARGET: VSTRING; ITEM: CHARACTER;
POSITION: STRINDEX := FIRST) return VSTRING;
-- Concatenation
function "&" (LEFT: VSTRING; RIGHT : VSTRING) return VSTRING;
function "&" (LEFT: VSTRING; RIGHT : STRING) return VSTRING;
function "&" (LEFT: VSTRING; RIGHT : CHARACTER) return VSTRING;
function "&" (LEFT: STRING; RIGHT : VSTRING) return VSTRING;
function "&" (LEFT: CHARACTER; RIGHT : VSTRING) return VSTRING;
-- Determine the position of a substring
function INDEX(WHOLE: VSTRING; PART: VSTRING; OCCURRENCE : NATURAL := 1)
return STRINDEX;
function INDEX(WHOLE : VSTRING; PART : STRING; OCCURRENCE : NATURAL := 1)
return STRINDEX;
function INDEX(WHOLE : VSTRING; PART : CHARACTER; OCCURRENCE : NATURAL := 1)
return STRINDEX;
function RINDEX(WHOLE: VSTRING; PART: VSTRING; OCCURRENCE : NATURAL := 1)
return STRINDEX;
function RINDEX(WHOLE : VSTRING; PART : STRING; OCCURRENCE : NATURAL := 1)
return STRINDEX;
function RINDEX(WHOLE : VSTRING; PART : CHARACTER; OCCURRENCE : NATURAL := 1)
return STRINDEX;
-- Conversion from other associated types
function VSTR(FROM : STRING) return VSTRING;
function VSTR(FROM : CHARACTER) return VSTRING;
function "+" (FROM : STRING) return VSTRING;
function "+" (FROM : CHARACTER) return VSTRING;
generic
type FROM is private;
type TO is private;
with function STR(X : FROM) return STRING is <>;
with function VSTR(Y : STRING) return TO is <>;
function CONVERT(X : FROM) return TO;
pragma PAGE;
\f
private
type VSTRING is
record
LEN : STRINDEX := STRINDEX'FIRST;
VALUE : STRING(FIRST .. LAST) := (others => ASCII.NUL);
end record;
NUL : constant VSTRING := (STRINDEX'FIRST, (others => ASCII.NUL));
end VSTRINGS;
--
-- .......................................................................... --
--
-- DISTRIBUTION AND COPYRIGHT:
--
-- This software is released to the Public Domain (note:
-- software released to the Public Domain is not subject
-- to copyright protection).
-- Restrictions on use or distribution: NONE
--
-- DISCLAIMER:
--
-- This software and its documentation are provided "AS IS" and
-- without any expressed or implied warranties whatsoever.
-- No warranties as to performance, merchantability, or fitness
-- for a particular purpose exist.
--
-- Because of the diversity of conditions and hardware under
-- which this software may be used, no warranty of fitness for
-- a particular purpose is offered. The user is advised to
-- test the software thoroughly before relying on it. The user
-- must assume the entire risk and liability of using this
-- software.
--
-- In no event shall any person or organization of people be
-- held responsible for any direct, indirect, consequential
-- or inconsequential damages or lost profits.