-- file PGSFormat.mesa -- last modified by Satterthwaite, July 14, 1980 12:47 PM DIRECTORY PGScondefs; PGSFormat: PROGRAM IMPORTS PGScondefs EXPORTS PGScondefs = BEGIN OPEN PGScondefs; leftindex, symindex, nextprod, sinfindex, nextrhschar, topsymbol:CARDINAL; rule, nextrule, aliasindex, lastterminal:CARDINAL; symstring, aliastext: Symtab; sinfo:Sinfo; pinfo:Pinfo; rhstext:Rhschar; KeyWord: TYPE = {binary, type, interface, module, goal, terminals, aliases, productions}; text: STRING = "BINARYTYPEINTERFACEMODULEGOALTERMINALSALIASESPRODUCTIONS"; textKeys: ARRAY KeyWord OF RECORD [index, len: CARDINAL] = [[0,6], [6,4], [10,9], [19,6], [25,4], [29,9], [38,7], [45,11]]; error: PROC = BEGIN FreeSegment[hashChain]; FreeSegment[BASE[rhstext]]; FreeSegment[BASE[sinfo]]; FreeSegment[BASE[pinfo]]; FreeSegment[BASE[symstring]]; FreeSegment[BASE[aliastext]]; ERROR PGSfail[] END; Directive: PROC [key: KeyWord] RETURNS [BOOLEAN] = BEGIN i:CARDINAL; IF symindex-leftindex-1 # textKeys[key].len OR symstring[symindex-1] # ': THEN RETURN [FALSE]; FOR i IN [0..textKeys[key].len) DO IF symstring[leftindex+i] # text[textKeys[key].index+i] THEN RETURN [FALSE] ENDLOOP; RETURN [TRUE]; END; ExtractKeyItem: PROC [key: KeyWord, value: STRING] RETURNS [BOOLEAN] = BEGIN i,j:CARDINAL; IF ~Directive[key] THEN RETURN [FALSE] ELSE BEGIN gettext[]; j ← 0; FOR i IN [leftindex..symindex) DO value[j] ← symstring[i]; j ← j+1 ENDLOOP; END; value.length ← j; RETURN [TRUE]; END; hashChain: POINTER TO ARRAY [1..61] OF CARDINAL; findtext: PROC RETURNS [CARDINAL] = BEGIN h,i,j,k:CARDINAL; h ← (256*(symindex-leftindex)+LOOPHOLE[symstring[leftindex],CARDINAL]) MOD 61 +1; j ← hashChain[h]; WHILE j#0 DO IF symindex-leftindex = sinfo[j+1].symptr-sinfo[j].symptr THEN -- same length BEGIN i ← sinfo[j].symptr; FOR k IN [leftindex..symindex) DO IF symstring[k]#symstring[i] THEN EXIT; i ← i+1; REPEAT FINISHED => {symindex ← leftindex; RETURN [j]}; ENDLOOP; END; j ← sinfo[j].link; ENDLOOP; -- new symbol sinfo[sinfindex] ← [leftindex,hashChain[h],0]; hashChain[h] ← sinfindex; sinfindex ← sinfindex+1; sinfo[sinfindex].symptr ← symindex; IF sinfindex=LENGTH[sinfo] THEN sinfo ← LOOPHOLE[expand[sinfo,SIZE[sinforec],LENGTH[sinfo]/8]]; RETURN [sinfindex-1]; END; Formatter: PROC [binaryFile, typeId, moduleFile, interfaceFile: STRING] = BEGIN i:CARDINAL; chain:BOOLEAN; outstring["-- file "L]; outstring[sourceName]; outstring[" rewritten by PGS, "L]; outtime[]; outeol[1]; ScanInit[]; DO gettext[]; SELECT TRUE FROM ExtractKeyItem[binary, binaryFile] => NULL; ExtractKeyItem[module, moduleFile] => NULL; ExtractKeyItem[type, typeId] => NULL; ExtractKeyItem[interface, interfaceFile] => NULL; ENDCASE => EXIT; ENDLOOP; IF ~Directive[goal] THEN error[] ELSE {symindex ← 0; gettext[]; sinfindex ← 1; [] ← findtext[]}; gettext[]; IF Directive[terminals] THEN BEGIN symindex ← leftindex; DO gettext[]; IF symstring[symindex-1] = ': AND (Directive[aliases] OR Directive[productions]) THEN EXIT; [] ← findtext[]; ENDLOOP; END; lastterminal ← sinfindex-1; aliasindex ← 0; IF Directive[aliases] THEN BEGIN symindex ← leftindex; DO gettext[]; IF Directive[productions] THEN EXIT; FOR i IN [leftindex..symindex) DO IF aliasindex=CARDINAL[cpw]*LENGTH[aliastext] THEN aliastext ← LOOPHOLE[ expand[LOOPHOLE[aliastext],SIZE[CARDINAL],LENGTH[aliastext]/8]]; aliastext[aliasindex] ← symstring[i]; aliasindex ← aliasindex+1; ENDLOOP; aliastext[aliasindex] ← ' ; aliasindex ← aliasindex+1; symindex ← leftindex; gettext[]; FOR i IN [leftindex..symindex) DO IF aliasindex=CARDINAL[cpw]*LENGTH[aliastext] THEN aliastext ← LOOPHOLE[ expand[LOOPHOLE[aliastext],SIZE[CARDINAL],LENGTH[aliastext]/8]]; aliastext[aliasindex] ← symstring[i]; aliasindex ← aliasindex+1; ENDLOOP; aliastext[aliasindex] ← ' ; aliasindex ← aliasindex+1; symindex ← leftindex; ENDLOOP; END; IF ~Directive[productions] THEN error[]; symindex ← leftindex; nextprod ← 1; nextrhschar ← 0; gettext[]; topsymbol ← findtext[]; DO -- exit from this loop on EndOfFIle, topsymbol distinguishes cases gettext[]; IF symstring[leftindex] = ': AND symstring[leftindex+1] = ': AND symstring[leftindex+2] = '= THEN BEGIN IF symindex-leftindex=4 AND symstring[leftindex+3]='C THEN chain ← TRUE ELSE IF symindex-leftindex=3 THEN chain ← FALSE ELSE GOTO notlhs; symindex ← leftindex; pinfo[nextprod] ← [rule,chain,0,nextrhschar]; IF (i ← sinfo[topsymbol].lhshead)=0 THEN sinfo[topsymbol].lhshead ← nextprod ELSE BEGIN oldi:CARDINAL ← 0; WHILE i#0 DO oldi ← i; i ← pinfo[i].link ENDLOOP; pinfo[oldi].link ← nextprod; END; nextprod ← nextprod+1; IF nextprod=LENGTH[pinfo] THEN pinfo ← LOOPHOLE[expand[pinfo,SIZE[pinforec],LENGTH[pinfo]/8]]; topsymbol ←0; gettext[]; topsymbol ← findtext[]; LOOP; EXITS notlhs => NULL; END; rhstext[nextrhschar] ← topsymbol; nextrhschar ← nextrhschar+1; IF nextrhschar = LENGTH[rhstext] THEN rhstext ← LOOPHOLE[ expand[rhstext, SIZE[CARDINAL], LENGTH[rhstext]/8] ]; topsymbol ← findtext[]; ENDLOOP; END; Format: PUBLIC PROC [binary, type, module, interface: STRING] = BEGIN i:CARDINAL; nextrule ← 0; symindex ← 0; hashChain ← AllocateSegment[61]; FOR i IN [0..61] DO hashChain[i] ← 0 ENDLOOP; rhstext ← LOOPHOLE[makearray[maxrhssymbols+1,SIZE[CARDINAL]]]; sinfo ← LOOPHOLE[makearray[symtabsize+1,SIZE[sinforec]]]; pinfo ← LOOPHOLE[makearray[maxprod+1,SIZE[pinforec]]]; symstring ← LOOPHOLE[makearray[500,SIZE[CARDINAL]]]; aliastext ← LOOPHOLE[makearray[100,SIZE[CARDINAL]]]; Formatter[binary, type, module, interface ! EndOfFile => CONTINUE]; -- always returns via catchphrase FreeSegment[hashChain]; IF topsymbol#0 THEN {rhstext[nextrhschar] ← topsymbol; nextrhschar ← nextrhschar+1}; sinfo[sinfindex].symptr ← symindex; pinfo[nextprod].rhsptr ← nextrhschar; END; PrintGrammar: PUBLIC PROC = BEGIN i, p, listindex:CARDINAL; list:Sinfo; rec:sinforec; noswap:BOOLEAN; printsymbol: PROC [i: CARDINAL] = BEGIN j:CARDINAL; outchar[' ,1]; FOR j IN [sinfo[i].symptr..sinfo[i+1].symptr) DO outchar[symstring[j],1] ENDLOOP; END; printprod: PROC [i,p: CARDINAL, first:BOOLEAN] = BEGIN j:CARDINAL; IF pinfo[p].chain THEN outstring["C "L]; outnum[pinfo[p].rule,3]; IF ~first THEN outstring[" |"L] ELSE {printsymbol[i]; outstring[" ::="L]}; FOR j IN [pinfo[p].rhsptr..pinfo[p+1].rhsptr) DO printsymbol[rhstext[j]] ENDLOOP; outeol[1]; END; outstring["||INPUT ||CHAIN ||LISTS ||TABLE1"L]; outeol[1]; IF lastterminal=1 THEN FOR i IN [2..sinfindex) DO IF sinfo[i].lhshead=0 THEN printsymbol[i] ENDLOOP ELSE FOR i IN [2..lastterminal] DO printsymbol[i] ENDLOOP; outstring[" eof"L]; outeol[1]; outstring["||TABLE2"L]; outeol[1]; printsymbol[1]; p ← 1; FOR i IN (lastterminal..sinfindex) DO IF sinfo[i].lhshead#0 THEN {printsymbol[i]; p ← p+1} ENDLOOP; IF aliasindex#0 THEN BEGIN outeol[1]; outstring["||TABLE3"L]; outeol[1]; FOR i IN [0..aliasindex) DO outchar[aliastext[i],1] ENDLOOP; END; outeol[1]; outstring["||TABLE4"L]; outeol[1]; list ← makearray[p,SIZE[sinforec]]; p ← sinfo[1].lhshead; list[0] ← [1,pinfo[p].rule,p]; listindex ← 1; FOR i IN (lastterminal..sinfindex) DO IF (p ← sinfo[i].lhshead)#0 THEN {list[listindex] ← [i,pinfo[p].rule,p]; listindex ← listindex+1}; ENDLOOP; FOR i DECREASING IN [0..LENGTH[list]) DO noswap ← TRUE; FOR p IN [0..i) DO IF list[p].link>list[p+1].link THEN {rec ← list[p]; list[p] ← list[p+1]; list[p+1] ← rec; noswap ← FALSE}; ENDLOOP; IF noswap THEN EXIT; ENDLOOP; FOR i IN [0..LENGTH[list]) DO p ← list[i].lhshead; printprod[list[i].symptr,p,TRUE]; p ← pinfo[p].link; WHILE p#0 DO printprod[0,p,FALSE]; p ← pinfo[p].link ENDLOOP; ENDLOOP; FreeSegment[BASE[list]]; FreeSegment[BASE[rhstext]]; FreeSegment[BASE[sinfo]]; FreeSegment[BASE[pinfo]]; FreeSegment[BASE[symstring]]; FreeSegment[BASE[aliastext]]; END; -- text input routines char: CHARACTER; -- current (most recently scanned) character EndOfFile: SIGNAL = CODE; gettext: PROC = BEGIN c:CHARACTER; WHILE char IN [0C..' ] DO IF char=ControlZ THEN WHILE char#CR DO outchar[char,1]; nextchar[]; ENDLOOP; outchar[char,1]; IF char=CR THEN BEGIN WHILE char IN [0C..' ] DO nextchar[]; outchar[char,1] ENDLOOP; c ← char; nextchar[]; outchar[char,1]; IF c#char OR c#'- THEN {nextchar[]; findheader[]}; END; nextchar[]; ENDLOOP; leftindex ← symindex; WHILE char ~IN [0C..' ] DO outchar[char,1]; IF symindex=CARDINAL[cpw]*LENGTH[symstring] THEN symstring ← LOOPHOLE[ expand[LOOPHOLE[symstring],SIZE[CARDINAL],LENGTH[symstring]/8]]; symstring[symindex] ← char; symindex ← symindex+1; nextchar[]; ENDLOOP; END; findheader: PROC = BEGIN bindex,i,j:CARDINAL; k:INTEGER; buffer: STRING = [2000]; -- line assembly area BufferOverflow:ERROR = CODE; putchar: PROC = BEGIN IF bindex = buffer.maxlength THEN ERROR BufferOverflow; buffer[bindex] ← char; bindex ← bindex+1; nextchar[]; END; DO BEGIN bindex ← 0; WHILE char IN [0C..' ] DO IF char=CR OR char=ControlZ THEN GOTO copyline; putchar[]; ENDLOOP; IF char ~IN ['0..'9] AND char#query THEN GOTO copyline; putchar[]; WHILE char IN ['0..'9] DO putchar[] ENDLOOP; WHILE char IN [0C..' ] DO IF char=CR OR char=ControlZ THEN GOTO copyline; putchar[]; ENDLOOP; IF char#'= THEN GOTO copyline; putchar[]; IF char#'> THEN GOTO copyline; putchar[]; WHILE char IN [0C..' ] DO IF char=CR OR char=ControlZ THEN GOTO copyline; putchar[]; ENDLOOP; IF char#'- THEN GOTO copyline; putchar[]; IF char#'- THEN GOTO copyline; FOR i ← bindex-1, i-1 WHILE buffer[i]#'= DO NULL ENDLOOP; k ← 0; FOR j IN [0..i) DO k ← IF buffer[j]=TAB THEN k+8 ELSE k+1 ENDLOOP; outnum[nextrule,k-2]; rule ← nextrule; nextrule ← nextrule+1; outchar[' ,2]; FOR j IN [i..bindex) DO outchar[buffer[j],1] ENDLOOP; outchar['-,1]; RETURN; EXITS copyline => BEGIN FOR i IN [0..bindex) DO outchar[buffer[i],1] ENDLOOP; outchar[char,1]; WHILE char#CR DO nextchar[]; outchar[char,1] ENDLOOP; nextchar[]; END; END; ENDLOOP; END; tB: POINTER TO PACKED ARRAY OF CHARACTER; tI, tMax: [0..TextChars]; tOrigin, tLimit: CARDINAL; tEnded: BOOLEAN; nextchar: PROC = BEGIN IF (tI←tI+1) = tMax THEN {IF tEnded THEN SIGNAL EndOfFile[]; FillTextBuffer[]}; char ← tB[tI]; END; ScanInit: PROC = BEGIN tLimit ← tMax ← 0; tEnded ← FALSE; FillTextBuffer[]; char ← tB[tI]; findheader[]; nextchar[]; END; FillTextBuffer: PROC = BEGIN tOrigin ← tLimit; IF tEnded THEN tMax ← 0 ELSE {[tB, tMax, tEnded] ← nextbuffer[]; tLimit ← tOrigin + tMax}; IF tMax = 0 THEN {tB[0] ← 0C; tMax ← 1}; tI ← 0; END; END.