(* ---------------------------------------------------------------------------- * $Id: MASSYM2.mi,v 1.5 1993/05/11 10:48:59 kredel Exp $ * ---------------------------------------------------------------------------- * This file is part of MAS. * ---------------------------------------------------------------------------- * Copyright (c) 1989 - 1992 Universitaet Passau * ---------------------------------------------------------------------------- * $Log: MASSYM2.mi,v $ * Revision 1.5 1993/05/11 10:48:59 kredel * Small changes in STINS * * Revision 1.4 1992/10/16 13:53:40 kredel * Errors found by Mocka corrected * * Revision 1.3 1992/10/15 16:27:54 kredel * Changed rcsid variable * * Revision 1.2 1992/02/12 17:32:33 pesch * Moved CONST definition to the right place * * Revision 1.1 1992/01/22 15:11:30 kredel * Initial revision * * ---------------------------------------------------------------------------- *) IMPLEMENTATION MODULE MASSYM2; (* MAS/SAC Symbol System Implementation module 2. *) (* Version: HASH-TABLE with AVL-TREEs for Symboltable *) (* Import lists and declarations. *) FROM MASELEM IMPORT GAMMAINT, MASEXP, MASQREM, MASREM; FROM MASSTOR IMPORT BETA, SIL, LIST, LISTVAR, LENGTH, SFIRST, SRED, LIST1, INV, ADV, FIRST, RED, COMP; FROM MASBIOS IMPORT BLINES, CREAD, CWRITE, CREADB, DIGIT, LETTER, LISTS, MASORD, GWRITE, DIBUFF, CHI, BKSP, SWRITE, TAB; FROM SACLIST IMPORT CLOUT, ADV2, CONC, COMP2, EQUAL, SECOND, RED2, AWRITE, AREAD, SLELT,ADV3; CONST rcsidi = "$Id: MASSYM2.mi,v 1.5 1993/05/11 10:48:59 kredel Exp $"; CONST copyrighti = "Copyright (c) 1989 - 1992 Universitaet Passau"; CONST ICOUNT = 1; (* ? *) VAR NAM, SBASE: GAMMAINT; VAR newIns: BOOLEAN; PROCEDURE ACOMP(A,B: LIST): LIST; (*Alphabetic comparison. A and B are symbols. t=+1,0,-1 according to whether A preceds, is equal, or follows B alphabetically.*) VAR TL: LIST; BEGIN (*1*) TL:=ACOMP1(NAME(A),NAME(B)); (*4*) RETURN(TL); END ACOMP; PROCEDURE ACOMP1(A,B: LIST): LIST; (*Alphabetic comparison, 1. subalgorithm. A and B are packed strings. s=-1,0,1 according to whether a preceds, is equal, or succeeds B alphabetically.*) VAR AL, AP, BL, BP, SL: LIST; BEGIN (*1*) (*initialize.*) AP:=A; BP:=B; SL:=0; (*2*) (*compare.*) REPEAT ADV(AP, AL,AP); ADV(BP, BL,BP); IF AL > BL THEN SL:=1; ELSE IF AL < BL THEN SL:=-1; END; END; IF SL <> 0 THEN RETURN(SL); END; UNTIL (AP = SIL) OR (BP = SIL); (*3*) (*end.*) IF BP <> SIL THEN SL:=-1; ELSE IF AP <> SIL THEN SL:=1; END; END; RETURN(SL); (*6*) END ACOMP1; PROCEDURE ASSOC(AL,L: LIST): LIST; (*Associate. L=(a1 b1, a2 b2, ...,a sub n b sub n), n ge 0, a is an object. If there is an i such that a=a sub i then P=(b sub i, ...,a sub n b sub n), otherwise P=().*) VAR ALP, P: LIST; BEGIN (*1*) (*initialize.*) P:=L; (*2*) (*search.*) WHILE P <> SIL DO ADV(P, ALP,P); IF AL = ALP THEN RETURN(P); END; ADV(P, ALP,P); END; (*5*) RETURN(P); END ASSOC; PROCEDURE ASSOCQ(AL,L: LIST): LIST; (*Associate equal. L=(a1 b1, a2 b2, ...,a sub n b sub n), n ge 0, a is an object. If there is an i such that a is equal to a sub i then P=(b sub i, ...,a sub n b sub n), otherwise P=().*) VAR ALP, P: LIST; BEGIN (*1*) (*initialize.*) P:=L; (*2*) (*search.*) WHILE P <> SIL DO ADV(P, ALP,P); IF EQUAL(AL,ALP) = 1 THEN RETURN(P); END; ADV(P, ALP,P); END; (*5*) RETURN(P); END ASSOCQ; PROCEDURE ATTRIB(L: LIST): LIST; (*Attribute. L is a symbol. Returns the attributes of L.*) VAR LP: LIST; BEGIN (*1*) (*initialize.*) LP:=SIL; (*2*) (*symbol.*) IF SYMBOL(L) THEN LP:=RED2(L) END; (*5*) RETURN(LP); END ATTRIB; PROCEDURE BEGINU(); (*Begin, universal. The symbolic system is initialized without initializing any subsystems. It is assumed, that at least BEGIN1 was called previously.*) VAR CL, NL, TL: LIST; BEGIN (*1*) (*initialize symbolic globals.*) SYMTB:=SIL; NL:=0; CL:=CHI+1; TL:=BETA DIV CL; REPEAT TL:=TL DIV CL; NL:=NL+1; UNTIL TL = 0; SBASE:=MASEXP(CL,NL); (*2*) (*translator options.*) TRMAX:=10; COUNT:=0; NAM:=0; (*3*) (*hiding type.*) NOSHOW:=ENTER(LISTS("NOSHOW")); (*5*) RETURN; END BEGINU; PROCEDURE EXPLOD(S: LIST): LIST; (*Explode symbol. S is a symbol, L its character list.*) VAR A, AP, CL, DL, J1Y, L, LP, Q: LIST; BEGIN (*1*) (*get packed character list.*) LP:=NAME(S); L:=SIL; CL:=CHI+1; (*2*) (*unpack characters.*) REPEAT DL:=SBASE DIV CL; ADV(LP, A,LP); REPEAT MASQREM(A,DL, Q,AP); A:=AP; J1Y:=Q-1; L:=COMP(J1Y,L); DL:=DL DIV CL; UNTIL A = 0; UNTIL LP = SIL; (*3*) (*exit*) L:=INV(L); (*6*) RETURN(L); END EXPLOD; PROCEDURE ENTER(L: LIST): LIST; (*Enter into symbol table. L is a character list, S the pointer to the corresponding symbol. If the symbol is not yet in the symbol table SYMTB, then a new node is created.*) VAR J1Y, S: LIST; BEGIN (*1*) J1Y:=PACK(L); S:=STINS(J1Y); (*4*) RETURN(S); END ENTER; PROCEDURE GENSYM(): LIST; (*Generate symbol. S is a newly generated symbol. NAM is advanced.*) VAR J1Y, Q, S: LIST; BEGIN (*1*) (*increase counter.*) NAM:=NAM+1; (*2*) (*create character list.*) S:=LIST1(MASORD("Y")); Q:=NAM; REPEAT J1Y:=MASREM(Q,10); S:=COMP(J1Y,S); Q:=Q DIV 10; UNTIL Q = 0; (*3*) (*enter in symbol table.*) J1Y:=COMP(MASORD("J"),S); S:=ENTER(J1Y); (*6*) RETURN(S); END GENSYM; PROCEDURE GET(S,AL: LIST): LIST; (*Get property. The property list of the symbol S is searched under indicator a. A is the property under a, if any, otherwise A is set to beta.*) VAR A: LIST; BEGIN (*1*) A:=ASSOC(AL,ATTRIB(S)); IF A <> SIL THEN A:=FIRST(A) END; (*4*) RETURN(A) END GET; PROCEDURE NAME(L: LIST): LIST; (*Name. L is a symbol. Returns the name of L.*) VAR LP: LIST; BEGIN (*1*) (*initialize.*) LP:=SIL; (*2*) (*symbol.*) IF SYMBOL(L) THEN LP:=SECOND(L) END; (*5*) RETURN(LP); END NAME; PROCEDURE PACK(L: LIST): LIST; (*Pack character list. L is a non-empty character list. B is the packed list.*) VAR A, B, BL, CL, DL, J1Y, LP: LIST; BEGIN (*1*) (*initialize.*) LP:=L; B:=SIL; BL:=CHI+1; A:=0; DL:=1; (*2*) (*process characters.*) REPEAT ADV(LP, CL,LP); IF DL = SBASE THEN B:=COMP(A,B); A:=0; DL:=1; END; DL:=DL*BL; J1Y:=A*BL; J1Y:=J1Y+CL; A:=J1Y+1; UNTIL LP = SIL; (*3*) (*shift left and invert.*) WHILE DL < SBASE DO DL:=DL*BL; A:=A*BL; END; J1Y:=COMP(A,B); B:=INV(J1Y); (*6*) RETURN(B); END PACK; PROCEDURE PUT(S,AL,A: LIST); (*Put. The property A is stored on the property list of the symbol S under the indicator a.*) VAR L: LIST; BEGIN (*1*) (*already there.*) L:=ASSOC(AL,ATTRIB(S)); IF L <> SIL THEN SFIRST(L,A); RETURN; END; (*2*) (*new entry.*) SRED(RED(S),COMP2(AL,A,ATTRIB(S))); (*5*) RETURN; END PUT; PROCEDURE REMPRP(S,AL: LIST); (*Remove property. Under indicator a on the property list of symbol S the property is removed.*) VAR BL, L, LP: LIST; BEGIN (*1*) (*initialize.*) L:=RED(S); LP:=RED(L); (*2*) (*search and remove.*) WHILE LP <> SIL DO ADV(LP, BL,LP); IF AL = BL THEN SRED(L,RED(LP)); RETURN END; L:=LP; LP:=RED(LP) END; (*5*) RETURN END REMPRP; PROCEDURE SMEMB(S,L: LIST): LIST; (*Symbol membership. S is a symbol, L a list containing possibly also symbols. b=1 if S or a copy of S occurs in L, b=0 otherwise.*) VAR BL, LP, SP, SS: LIST; BEGIN (*1*) (*initilize.*) LP:=L; BL:=1; SP:=SECOND(S); (*2*) (*search.*) WHILE LP <> SIL DO ADV(LP, SS,LP); IF SYMBOL(SS) AND (ACOMP1(NAME(SS),SP) = 0) THEN RETURN(BL) END; END; (*3*) (*exit.*) BL:=0; (*6*) RETURN(BL) END SMEMB; PROCEDURE SREAD(): LIST; (*Symbol read. The next symbol is read from input. S is the symbol in the symbol table SYMTB.*) VAR J1Y, S: LIST; BEGIN (*1*) J1Y:=SREAD1(); S:=ENTER(J1Y); (*4*) RETURN(S); END SREAD; PROCEDURE SREAD1(): LIST; (*Symbol read, 1. The first non-alphanumeric character of the input stream terminates the symbol. L is the character list of the symbol, which is not entered in the symbol table.*) VAR C, L: LIST; BEGIN (*1*) (*skip leading blanks.*) L:=SIL; C:=CREADB(); IF NOT LETTER(C) THEN SWRITE("No symbol found by SREAD1"); DIBUFF; L:=LISTS("???"); RETURN(L) END; (*2*) (*collect characters.*) REPEAT L:=COMP(C,L); C:=CREAD(); UNTIL NOT DIGIT(C) AND NOT LETTER(C); BKSP; L:=INV(L); (*5*) RETURN(L); END SREAD1; PROCEDURE SYMBOL(AP: LIST): BOOLEAN; (*Symbol. AP is an object. Returns true if it is a symbol and false else.*) VAR BL: BOOLEAN; BEGIN (*1*) BL:=FALSE; IF AP > BETA THEN IF FIRST(AP) = -BETA THEN BL:=TRUE END END; (*4*) RETURN(BL); END SYMBOL; PROCEDURE SYNEW(L: LIST): LIST; (*Symbol new. L is a packed character list.*) VAR S: LIST; BEGIN (*1*) S:=COMP(-BETA,COMP(L,SIL)); (*4*) RETURN(S); END SYNEW; PROCEDURE SymSummary(); (*Summary of symbol system. The number of symbols in SYMTB and the number of their properties is written.*) VAR P, S: LIST; i: CARDINAL; BEGIN (* (*0*) (*test.*) BLINES(2); SWRITE("SYMTBarr = "); BLINES(1); FOR i:=0 TO maxtab DO SWRITE("["); AWRITE(i); SWRITE("] = "); UWRITE(SYMTBarr[i]); IF SYMTBarr[i] < SIL THEN SYMTBarr[i]:=SIL END; END; *) (*1*) (*count symbols and their properties.*) BLINES(2); STCNT(SYMTB,S,P); (* SYMTB dummy ! *) AWRITE(S); SWRITE(" symbols and "); AWRITE(P); SWRITE(" properties."); BLINES(1); (*debug*) STWRT(SYMTB); (* SYMTB dummy ! *) (*gubed*) (*5*) END SymSummary; PROCEDURE SYWRIT(S: LIST); (*Symbol write. The symbol S is written in the output stream.*) VAR N, L: LIST; BEGIN (*1*) (*get unpacked name.*) N:=EXPLOD(S); (*2*) (*transmit.*) CLOUT(N); (*5*) END SYWRIT; PROCEDURE SUBLIS(L,A: LIST): LIST; (*Substitution with list. L=(x1 e1, ...,x sub n e sub n), a and e sub i are objects. The x sub i are beta-digits or pointers to uniquely stored lists like symbols. B is A with the x sub i substituted by the e sub i.*) VAR B, C1, C2, J1Y, J2Y: LIST; BEGIN (*1*) (*basis.*) B:=ASSOC(A,L); IF B <> SIL THEN B:=FIRST(B); RETURN(B); END; IF (A <= BETA) OR SYMBOL(A) THEN B:=A; RETURN(B); END; (*2*) (*recursion.*) ADV(A, C1,C2); J1Y:=SUBLIS(L,C1); J2Y:=SUBLIS(L,C2); B:=COMP(J1Y,J2Y); (*5*) RETURN(B); END SUBLIS; PROCEDURE UREAD(): LIST; (*Universal read. The next atom, symbol, string or list over atoms, strings and symbols is read and stored under L. Blanks may occur anywhere. Elements of a list may or may not be separated by a comma.*) VAR C, J1Y, L: LIST; BEGIN (*1*) (*BRANCH ON C.*) L:=SIL; C:=CREADB(); IF DIGIT(C) OR (C = MASORD("-")) OR (C = MASORD("+")) THEN BKSP; L:=AREAD(); RETURN(L) END; IF LETTER(C) THEN BKSP; L:=SREAD(); RETURN(L) END; IF C = MASORD('"') THEN LOOP C:=CREAD(); IF C = MASORD('"') THEN C:=CREAD(); IF C <> MASORD('"') THEN BKSP; EXIT END; END; L:=COMP(C,L); END; L:=INV(L); RETURN(L) END; IF C <> MASORD("(") THEN SWRITE("Atoms, strings, symbols, or lists expected by UREAD, "); CWRITE(C); SWRITE(" found."); DIBUFF; RETURN(0) END; (*2*) (*READ LIST.*) C:=CREADB(); IF C = MASORD(")") THEN RETURN(L); END; BKSP; LOOP J1Y:=UREAD(); L:=COMP(J1Y,L); C:=CREADB(); IF C = MASORD(")") THEN L:=INV(L); RETURN(L) END; IF C <> MASORD(",") THEN BKSP; END; END; (*5*) END UREAD; PROCEDURE UWRITE(L: LIST); (*Universal write. L is an atom, symbol or a list over atoms and symbols. L is written in the output stream, followed by BLINES(0). *) BEGIN (*1*) UWRIT1(L); BLINES(0); (*4*) RETURN; END UWRITE; PROCEDURE UWRIT1(L: LIST); (*Universal write, 1. subalgorithm. L is an atom, a symbol or a list over atoms or symbols. L is written in the output stream. *) VAR AL, LP: LIST; BEGIN (*1*) (*ATOM OR SYMBOL.*) IF L < BETA THEN AWRITE(L); RETURN END; IF SYMBOL(L) THEN SYWRIT(L); RETURN END; (*2*) (*LIST.*) SWRITE("("); LP:=L; WHILE LP <> SIL DO ADV(LP, AL,LP); UWRIT1(AL); IF AL = NOSHOW THEN SWRITE(" ..."); LP:=SIL END; IF LP <> SIL THEN SWRITE(" ") END END; SWRITE(")"); (*5*) END UWRIT1; (*************************************************************************) (* MODULE SymbolTableAccess; (* by Thomas Wollersberger December 1990, modified AVL-Version *) (* Version HASH+AVL *) IMPORT LIST,SIL,ADV2,COMP,ACOMP1,NAME,SYNEW,SRED,RED,SFIRST, UWRIT1,UWRITE,GET,ICOUNT,COUNT,LENGTH,TAB,BLINES,ADV, LISTVAR,SWRITE,CONC,ATTRIB,FIRST,ADV3,SLELT,RED2; EXPORT STINS,STCNT,STLST,STLSTI,STSRCH,STWRT; *) CONST maxtab = 498; (* length of hashtable *) (* good values: 112,192,!198!,210,222,306,!498!,996 *) (* more symbols -> more tableplaces *) CONST maxtab1 = maxtab + 1; VAR SYMTBarr : ARRAY [0..maxtab] OF LIST; (* Remark : All procedures have access to the same symboltable, here implemented as an Hash-table with AVL-trees for collision resolution. The varible SYMTB of type LIST defined in the definition-module is never used (It's only history !). The procedures parametrisized with a Symboltable will only use the Hash-table defined in this local module (incidentally it is named SYMTBarr, too !). You can use the outer SYMTB as a dummy-variable. Th.W. *) PROCEDURE hash(name:LIST): CARDINAL; (* computes a number (0..maxtab) from the packed character list name. The numbers should be distributed very uniform, but that depends on the average structure of the names. Three possiblities are tested : *) (* 1. Simply take 16 Bits of the Coding of the first characters ! *) (* fastest version *) (* VAR f:LIST; BEGIN f:=FIRST(name); (*Assert f >= 0 *) RETURN(CARDINAL(f) MOD maxtab1) *) (* 2. Simply take the Coding of the first characters ! *) VAR f:LIST; BEGIN f:=FIRST(name); (*Assert f >= 0 *) RETURN(CARDINAL(f MOD maxtab1)) (* 3. Sum up over all characters ! *) (* VAR s:CARDINAL; f:LIST; BEGIN s:=0; WHILE name # SIL DO ADV(name, f,name); s:=(s+CARDINAL(f MOD maxtab1)) MOD maxtab1 END; RETURN(s) *) END hash; PROCEDURE SearchInsertAVL (B, t:LIST; VAR S: LIST; VAR HeightChanged:BOOLEAN): LIST; (* For further documentation see any book on AVL-trees ! *) VAR lt,bal,elem,rt: LIST; tt, lth,balh,rth,lth1,rth1: LIST; BEGIN tt:=t; IF t=SIL (* empty tree *) THEN S:=SYNEW(B); tt:=COMP(SIL,COMP(0,COMP(S,SIL))); HeightChanged:=TRUE; newIns:=TRUE ELSE ADV3(t, lt,bal,elem,rt); CASE INTEGER(ACOMP1(B,NAME(elem))) OF -1: (* search/insert left *) lt:=SearchInsertAVL(B, lt, S,HeightChanged); IF newIns THEN SFIRST(t,lt); newIns:=FALSE END; IF HeightChanged (* reset balance *) THEN CASE INTEGER(bal) OF -1: ADV3(lt, lth,balh,elem,rth); IF balh=-1 THEN (* LL-Rotation *) SFIRST(t,rth); SRED(RED2(lt),t); SLELT(t,2,0); tt:=lt; newIns:=TRUE ELSE (* LR-Rotation *) ADV3(rth, lth1,balh,elem,rth1); SRED(RED2(lt),lth1); SFIRST(rth,lt); SFIRST(t,rth1); SRED(RED2(rth),t); IF balh=-1 THEN SLELT(t,2,1) ELSE SLELT(t,2,0) END; IF balh=1 THEN SLELT(lt,2,-1) ELSE SLELT(lt,2,0) END; tt:=rth; newIns:=TRUE END; SLELT(t,2,0); HeightChanged:=FALSE | 0: SLELT(t,2,-1) | 1: SLELT(t,2,0); HeightChanged:=FALSE END END (* IF HeightChanged *) | 0: (* Symbol found *) S:=elem; HeightChanged:=FALSE | 1: (* search/insert right *) rt:=SearchInsertAVL(B, rt, S,HeightChanged); IF newIns THEN SRED(RED2(t),rt); newIns:=FALSE END; IF HeightChanged (* reset balance *) THEN CASE INTEGER(bal) OF -1: SLELT(t,2,0); HeightChanged:=FALSE | 0: SLELT(t,2,1) | 1: ADV3(rt, lth,balh,elem,rth); IF balh=1 THEN (* RR-Rotation *) SRED(RED2(t),lth); SFIRST(rt,t); SLELT(t,2,0); tt:=rt; newIns:=TRUE; ELSE (* RL-Rotation *) ADV3(lth, lth1,balh,elem,rth1); SFIRST(rt,rth1); SRED(RED2(lth),rt); SRED(RED2(t),lth1); SFIRST(lth,t); IF balh=1 THEN SLELT(t,2,-1) ELSE SLELT(t,2,0) END; IF balh=-1 THEN SLELT(rt,2,1) ELSE SLELT(rt,2,0) END; tt:=lth; newIns:=TRUE END; SLELT(t,2,0); HeightChanged:=FALSE END END (* IF HeightChanged *) END (* CASE *) END; (* IF *) RETURN(tt); END SearchInsertAVL; PROCEDURE STINS(B: LIST): LIST; (* Symbol table insertion. B is a packed list of characters. S is a pointer to the corresponding symbol in the symbol table. If it is not yet in, a new node is created. *) VAR h: BOOLEAN; S: LIST; n: CARDINAL; BEGIN newIns:=FALSE; h:=FALSE; S:=SIL; n:=hash(B); SYMTBarr[n]:=SearchInsertAVL( B, SYMTBarr[n], S, h ); (* computes symbol S for name B *) RETURN(S) END STINS; PROCEDURE STCNT(T: LIST; VAR S,P: LIST); (* Symbol table count. T is a dummy list, S is the number of symbols in T, P the number of properties of all symbols of the tree. Since every symbol has a name property, P ge S. *) VAR bal: LIST; PROCEDURE STCNTrec(T: LIST; VAR S,P: LIST); VAR J1Y,K,L,PP,R,SP: LIST; BEGIN IF T = SIL THEN S:=0; P:=0 ELSE ADV3(T, L,bal,K,R); STCNTrec(L, S,P); (* left branch *) S:=S+1; J1Y:=LENGTH(K); J1Y:=J1Y DIV 2; P:=P+J1Y; IF (COUNT >= 1) AND (GET(K,ICOUNT) <> SIL) THEN UWRIT1(K); TAB(8); UWRITE(GET(K,ICOUNT)) END; STCNTrec(R, SP,PP); (* right branch *) S:=S+SP; P:=P+PP END END STCNTrec; VAR s1,p1:LIST; i: CARDINAL; BEGIN S:=0; P:=0; FOR i:=0 TO maxtab DO STCNTrec(SYMTBarr[i], s1,p1); S:=S+s1; P:=P+p1 (* sum up over array *) END END STCNT; PROCEDURE STLST(T: LIST): LIST; (* Symbol table list. T is a dummy list. L is the list of its symbols in alphabetic order. *) VAR bal,J1Y: LIST; PROCEDURE STLST1tree(T: LIST): LIST; (* inorder list *) VAR LL,RL,SL: LIST; BEGIN IF T = SIL THEN RETURN(SIL) END; ADV2(T, LL,SL,RL); (* left tree,symbol,right tree *) IF LL <> SIL THEN LL:=STLST1tree(LL) END; IF RL <> SIL THEN RL:=STLST1tree(RL) END; J1Y:=COMP(SL,RL); RETURN( CONC(LL,J1Y) ) END STLST1tree; VAR AuxTree:LIST; PROCEDURE WalkThroughTreeAndInsertIntoAuxtree(T:LIST); (* Elements of AVL-tree T are inserted into normal binary tree *) PROCEDURE insert(sym:LIST); (* local proc. for inserting into AuxTree *) VAR h,l,m,r:LIST; BEGIN IF AuxTree=SIL THEN (* new root *) AuxTree:=COMP(SIL,COMP(sym,SIL)) ELSE (* scan tree *) h:=AuxTree; LOOP (* trace one path until one fitting empty leave is found *) ADV2(h, l,m,r); CASE INTEGER(ACOMP1(NAME(m),NAME(sym))) OF -1: IF r=SIL THEN SRED(RED(h),COMP(SIL,COMP(sym,SIL))); EXIT ELSE h:=r END | 1: IF l=SIL THEN SFIRST(h,COMP(SIL,COMP(sym,SIL))); EXIT ELSE h:=l END END (* CASE *) END (* LOOP *) END (* IF *) END insert; VAR L,M,R:LIST; BEGIN IF T # SIL THEN ADV3(T, L,bal,M,R); (* cut from tree T and insert into AuxTree *) insert(M); (* I take preorder, because I expect in-(~alphabetic-)order to produce very unbalanced trees ! *) WalkThroughTreeAndInsertIntoAuxtree(L); WalkThroughTreeAndInsertIntoAuxtree(R) END END WalkThroughTreeAndInsertIntoAuxtree; VAR i:CARDINAL; BEGIN (* insert all elements of the table into an auxiliary binary tree *) AuxTree:=SIL; FOR i:=0 TO maxtab DO WalkThroughTreeAndInsertIntoAuxtree(SYMTBarr[i]) END; RETURN( STLST1tree(AuxTree) ) (* inorder-traverse AuxTree *) END STLST; PROCEDURE STLSTI(T: LIST): LIST; (* Symbol table list, internal-order (quick to compute). T is a dummy list, L is the list of the symbols. *) VAR bal,J1Y: LIST; PROCEDURE STLSTIrec(T: LIST): LIST; (* preorder list *) VAR LL,RL,SL: LIST; BEGIN IF T = SIL THEN RETURN(SIL) END; ADV3(T, LL,bal,SL,RL); IF LL <> SIL THEN LL:=STLSTIrec(LL) END; IF RL <> SIL THEN RL:=STLSTIrec(RL) END; J1Y:=CONC(LL,RL); RETURN( COMP(SL,J1Y) ) END STLSTIrec; VAR L:LIST; i:CARDINAL; BEGIN (* compute a list from every tree, concatenate them all. *) L:=SIL; FOR i:=0 TO maxtab DO L:=CONC(L, STLSTIrec(SYMTBarr[i]) ) END; RETURN(L) END STLSTI; PROCEDURE STSRCH(T,AP: LIST): LIST; (* Symbol table search. T is a dummy list, AP is a packed list of characters. If the symbol with the name AP occurs already in the symbol table T then S points to the entry and otherwise S=(). *) VAR l,b,m,r: LIST; BEGIN T:=SYMTBarr[hash(AP)]; (* hash the fitting tree *) WHILE T # SIL DO (* walk through until you find or not. *) ADV3(T, l,b,m,r); CASE INTEGER(ACOMP1(NAME(m),AP)) OF -1: T:=r | 0: RETURN(m) | (* found *) 1: T:=l END END; RETURN(SIL) (* not found *) END STSRCH; PROCEDURE STWRT(T: LIST); (*Symbol table write. T is a dummy list. The symbols followed by their properties are printed in alphabetic order. *) VAR a,M,ML:LIST; BEGIN T:=STLST(T); (* Now T is a list of the symbols in alphabetical order *) WHILE T # SIL DO (* Walk through list *) ADV(T, a,T); UWRIT1(a); SWRITE(": "); M:=ATTRIB(a); WHILE M <> SIL DO ADV(M, ML,M); UWRIT1(ML); SWRITE(" ") END; BLINES(0) END END STWRT; (* Initialisation of Hash-table of AVL-trees : *) VAR i:CARDINAL; BEGIN FOR i:=0 TO maxtab DO LISTVAR(SYMTBarr[i]); SYMTBarr[i]:=SIL END; (* END SymbolTableAccess; (*************************************************************************) (* Initialization. *) BEGIN *) LISTVAR(SYMTB); (* SYMTB is Dummy-Variable here !! *) BEGINU; END MASSYM2. (* -EOF- *)