(* ---------------------------------------------------------------------------- * $Id: SACSYM.mi,v 1.3 1992/10/15 16:27:55 kredel Exp $ * ---------------------------------------------------------------------------- * This file is part of MAS. * ---------------------------------------------------------------------------- * Copyright (c) 1989 - 1992 Universitaet Passau * ---------------------------------------------------------------------------- * $Log: SACSYM.mi,v $ * Revision 1.3 1992/10/15 16:27:55 kredel * Changed rcsid variable * * Revision 1.2 1992/02/12 17:32:35 pesch * Moved CONST definition to the right place * * Revision 1.1 1992/01/22 15:11:32 kredel * Initial revision * * ---------------------------------------------------------------------------- *) IMPLEMENTATION MODULE SACSYM; (* SAC Symbol System Implementation module. *) (* 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; CONST ICOUNT = 1; (* ? *) VAR NAM, SBASE: GAMMAINT; CONST rcsidi = "$Id: SACSYM.mi,v 1.3 1992/10/15 16:27:55 kredel Exp $"; CONST copyrighti = "Copyright (c) 1989 - 1992 Universitaet Passau"; 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; (*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 STCNT(T: LIST; VAR S,P: LIST); (*Symbol table tree count. T is a symbol tree, 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 J1Y, K, L, PP, R, SP: LIST; BEGIN (*1*) (*basis.*) IF T = SIL THEN S:=0; P:=0; RETURN; END; (*2*) (*left branch.*) ADV2(T, L,K,R); STCNT(L, S,P); (*3*) (*process symbol.*) 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; (*4*) (*right branch.*) STCNT(R, SP,PP); S:=S+SP; P:=P+PP; (*7*) RETURN; END STCNT; PROCEDURE STINS(B: LIST): LIST; (*Symbol tree 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 L, N, R, S, SP, T, TP: LIST; s: INTEGER; BEGIN (*1*) (*symbol table.*) T:=SYMTB; (*2*) (*binary search.*) WHILE T <> SIL DO ADV2(T, L,SP,R); s:=INTEGER(ACOMP1(NAME(SP),B)); CASE s OF -1 : TP:=T; T:=R; | 0 : S:=SP; RETURN(S); | 1 : TP:=T; T:=L; END; END; (*3*) (*insert new node.*) S:=SYNEW(B); N:=STNEW(S); IF SYMTB = SIL THEN SYMTB:=N; ELSE IF s = -1 THEN SRED(RED(TP),N); ELSE SFIRST(TP,N); END; END; (*6*) RETURN(S); END STINS; PROCEDURE STLST(T: LIST): LIST; (*Symbol tree list. T is a symbol tree, L is the list of its symbols in alphabetic order.*) VAR J1Y, L, LL, RL, SL: LIST; BEGIN (*1*) (*basis.*) IF T = SIL THEN L:=SIL; RETURN(L); END; (*2*) (*recursion.*) ADV2(T, LL,SL,RL); IF LL <> SIL THEN LL:=STLST(LL); END; IF RL <> SIL THEN RL:=STLST(RL); END; J1Y:=COMP(SL,RL); L:=CONC(LL,J1Y); (*5*) RETURN(L); END STLST; PROCEDURE STLSTI(T: LIST): LIST; (*Symbol tree list, in-order. T is a binary tree of symbols, L is a list of its symbols, with the root symbol appearing first.*) VAR J1Y, L, LL, RL, SL: LIST; BEGIN (*1*) (*basis.*) IF T = SIL THEN L:=SIL; RETURN(L); END; (*2*) (*recursion.*) ADV2(T, LL,SL,RL); IF LL <> SIL THEN LL:=STLSTI(LL); END; IF RL <> SIL THEN RL:=STLSTI(RL); END; J1Y:=CONC(LL,RL); L:=COMP(SL,J1Y); (*5*) RETURN(L); END STLSTI; PROCEDURE STNEW(L: LIST): LIST; (*Symbol tree new. L is symbol.*) VAR S: LIST; BEGIN (*1*) S:=COMP(SIL,COMP(L,SIL)); (*4*) RETURN(S); END STNEW; PROCEDURE STSRCH(T,AP: LIST): LIST; (*Symbol tree search. T is a binary tree of symbols, AP is a packed list of characters. If the symbol with the name AP occurs already in the symbol table T then S=() and otherwise S points to the entry.*) VAR K, L, R, S, TP, TPP: LIST; s: INTEGER; BEGIN (*1*) (*initialize.*) S:=SIL; TPP:=T; (*2*) (*binary search.*) IF TPP <> SIL THEN REPEAT TP:=TPP; ADV2(TP, L,K,R); s:=INTEGER(ACOMP1(NAME(K),AP)); CASE s OF -1 : TPP:=R; | 0 : S:=K; RETURN(S); | 1 : TPP:=L; | END; UNTIL TPP = SIL; END; (*5*) RETURN(S); END STSRCH; PROCEDURE STWRT(T: LIST); (*Symbol tree write. T is a binary tree of symbols. The symbols followed by their properties are printed in alphabetic order.*) VAR K, L, M, ML, R, TP: LIST; BEGIN (*1*) TP:=T; WHILE TP <> SIL DO ADV2(TP, L,K,R); STWRT(L); UWRIT1(K); SWRITE(": "); M:=ATTRIB(K); WHILE M <> SIL DO ADV(M, ML,M); UWRIT1(ML); SWRITE(" ") END; BLINES(0); TP:=R; END; (*4*) RETURN; END STWRT; 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; BEGIN (*1*) (*count symbols and their properties.*) BLINES(2); STCNT(SYMTB,S,P); AWRITE(S); SWRITE(" SYMBOLS AND "); AWRITE(P); SWRITE(" PROPERTIES."); BLINES(1); (*debug*) STWRT(SYMTB); (*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 or list over atoms 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 SWRITE("ATOMS, 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 followed by a blank character, but not by BLINES. *) 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 LP <> SIL THEN SWRITE(" ") END END; SWRITE(")"); (*5*) END UWRIT1; PROCEDURE TRC(VAR SP: ARRAY OF CHAR; AL1,AL2,AL3,AL4,AL5,AL6,AL7,AL8,AL9,AL10,AL11,AL12,AL13: LIST); (*Trace input or output. The first argument is the characters of an algorithm name, followed by +i for input tracing and by -i for output tracing. The following arguments are input or output parameters. *) VAR A: ARRAY[1..13] OF LIST; VAR BL, CL, J1Y, JL, S: LIST; IL: INTEGER; BEGIN (*1*) (*load.*) A[1]:=AL1; A[2]:=AL2; A[3]:=AL3; A[4]:=AL4; A[5]:=AL5; A[6]:=AL6; A[7]:=AL7; A[8]:=AL8; A[9]:=AL9; A[10]:=AL10; A[11]:=AL11; A[12]:=AL12; A[13]:=AL13; (*2*) (*form algorithm name.*) S:=ENTER(LISTS(SP)); (*3*) (*count.*) CL:=GET(S,ICOUNT); IF CL = SIL THEN CL:=0; END; IF A[1] < 0 THEN CL:=CL+1; PUT(S,ICOUNT,CL); END; IF (CL > TRMAX) OR (COUNT >= 1) THEN RETURN; END; (*4*) (*input.*) IF A[1] < 0 THEN (*indent*) SWRITE("+"); UWRIT1(S); FOR IL:=2 TO INTEGER(A[1]) DO GWRITE(GAMMAINT(IL-1)); SWRITE("."); UWRIT1(A[IL]); END; BLINES(0); RETURN; END; (*5*) (*output trace.*) SWRITE("-"); UWRIT1(S); FOR IL:=2 TO INTEGER(-A[1]) DO GWRITE(GAMMAINT(IL-1)); SWRITE("."); UWRIT1(A[IL]); END; IF CL > 0 THEN (*undent*) END; BLINES(0); (*8*) RETURN; END TRC; (* Initialization. *) BEGIN LISTVAR(SYMTB); BEGINU; END SACSYM. (* -EOF- *)