-- 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; <> 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;