DIRECTORY NPGSConDefs, NPGSTypes; NPGSLALR: CEDAR PROGRAM IMPORTS NPGSConDefs EXPORTS NPGSConDefs = { stateInfo: NPGSTypes.StateInfo; table: NPGSTypes.Table; lineWidth: CARDINAL; lalrSuccess: BOOL; entryLim: CARDINAL; -- index into table six: CARDINAL; -- six, the current state; sLim in NPGScan the next state number allocated hashHead: NPGSTypes.HashHeadsRef; top, rlim: CARDINAL; -- global to all incarnations of the recursive procedure context predState, symbol: CARDINAL; -- local variables of context shared by all incarnations backChain: NPGSTypes.BackChain; stack: NPGSTypes.Stack; chainStack: NPGSTypes.ChainStack; bitsInfo: NPGSTypes.BitsInfo; bitString: NPGSTypes.BitString; firstBits: NPGSTypes.BitString; LALRGen: PUBLIC PROC [cusp: BOOL] RETURNS[BOOL] = { i, j, k, totalShifts, totalReduces, oldEntries, firstOrCount: CARDINAL; redEntries, maxRedEntries, defaultProd: CARDINAL; conflictFlag, reduceFlag, messageFlag: BOOL; conflicts: NPGSTypes.Table; PrintHeader: PROC = { j, p: CARDINAL; NPGSConDefs.outeol[2]; FOR i: CARDINAL DECREASING IN (stateInfo[six+1].nucleus..stateInfo[six].nucleus] DO [,j,p] ¬ table[i]; IF lineWidth = 0 THEN { NPGSConDefs.outnum[six,4]; NPGSConDefs.outchar[' ,1]; lineWidth ¬ NPGSConDefs.tokenSize+5; IF p>0 THEN NPGSConDefs.outchar[' ,NPGSConDefs.tokenSize-NPGSConDefs.OutToken[NPGSConDefs.rhsChar[NPGSConDefs.prodInfo[p].index+j-1]]] }; IF lineWidth+9 > NPGSConDefs.outbufLim THEN {NPGSConDefs.outeol[1]; NPGSConDefs.outchar[' ,lineWidth ¬ NPGSConDefs.tokenSize+5]}; NPGSConDefs.outnum[p,4]; NPGSConDefs.outnum[j,3]; NPGSConDefs.outchar['/,1]; NPGSConDefs.outchar[' ,1]; ENDLOOP; NPGSConDefs.outeol[1] }; PrintEntry: PROC[ item: NPGSTypes.ItemRec, symmark: CARDINAL, sign: CHAR¬'-] = { i: INTEGER; p, j: CARDINAL; IF item.tag = 2 THEN { NPGSConDefs.outstring[" Reduce with "]; NPGSConDefs.outnum[item.pss,5,sign]; NPGSConDefs.outeol[1] } ELSE { i ¬ item.pss; IF item.tag # 0 THEN i ¬ -i; IF symmark = 0 THEN { [,j,p] ¬ IF item.tag=0 THEN table[stateInfo[item.pss].nucleus] ELSE item; symmark ¬ NPGSConDefs.rhsChar[NPGSConDefs.prodInfo[p].index+j-1] }; lineWidth ¬ lineWidth+NPGSConDefs.tokenSize+8; IF lineWidth > NPGSConDefs.outbufLim THEN {NPGSConDefs.outeol[1]; lineWidth ¬ NPGSConDefs.tokenSize+8}; NPGSConDefs.outnum[i,5,sign]; NPGSConDefs.outchar[' ,1]; NPGSConDefs.outchar[' ,NPGSConDefs.tokenSize+2-NPGSConDefs.OutToken[symmark]] } }; PrintState: PROC = { i, j: CARDINAL; lineWidth ¬ 0; PrintHeader[]; lineWidth ¬ 0; i ¬ stateInfo[six].entries; WHILE i totalShifts ¬ totalShifts+1; 2 => totalReduces ¬ totalReduces+1; ENDCASE; ENDLOOP ENDLOOP; IF NPGSConDefs.flags[printLR] THEN NPGSConDefs.outeol[1]; NPGSConDefs.closeoutstream[]; IF ~NPGSConDefs.flags[lists] AND ~NPGSConDefs.flags[printLALR] THEN RETURN[FALSE]; backChain ¬ NPGSConDefs.MakeBackChain[totalShifts+1]; FOR six IN [0..NPGSConDefs.sLim) DO stateInfo[six].link ¬ 0 ENDLOOP; k ¬ 1; FOR six IN [1..NPGSConDefs.sLim) DO FOR i IN [stateInfo[six].entries..stateInfo[six+1].entries) DO IF table[i].tag = 0 THEN { -- transition from six to table[i].pss backChain[k].state ¬ six; backChain[k].link ¬ stateInfo[table[i].pss].link; stateInfo[table[i].pss].link ¬ k; k ¬ k+1 }; ENDLOOP; ENDLOOP; NPGSConDefs.bitstrSize ¬ (NPGSConDefs.eofMark+NPGSConDefs.wordLength-1)/NPGSConDefs.wordLength; firstBits ¬ NPGSConDefs.MakeBitString[(NPGSConDefs.totalTokens-NPGSConDefs.eofMark+1), NPGSConDefs.bitstrSize]; FirstSet[]; firstOrCount ¬ NPGSConDefs.orCount; hashHead­ ¬ ALL[0]; -- used by find bitsInfo ¬ NPGSConDefs.MakeBitsInfo[NPGSConDefs.maxContexts]; rlim ¬ 1; bitString ¬ NPGSConDefs.MakeBitString[NPGSConDefs.maxContexts, NPGSConDefs.bitstrSize]; stack ¬ NPGSConDefs.MakeStack[30]; top ¬ 0; chainStack ¬ NPGSConDefs.MakeStack[90]; conflicts ¬ NPGSConDefs.MakeTable[NPGSConDefs.totalTokens+1]; messageFlag ¬ FALSE; NPGSConDefs.tEntries ¬ NPGSConDefs.ntEntries ¬ oldEntries ¬ 0; IF NPGSConDefs.flags[lists] THEN NPGSConDefs.openwordstream[]; FOR six IN [1..NPGSConDefs.sLim) DO FOR i IN [1..NPGSConDefs.totalTokens] DO conflicts[i] ¬ [0,0,0] ENDLOOP; i ¬ stateInfo[six].entries; WHILE i < stateInfo[six+1].entries DO SELECT table[i].tag FROM 0 => { j, p: CARDINAL; [,j,p] ¬ table[stateInfo[table[i].pss].nucleus]; conflicts[NPGSConDefs.rhsChar[NPGSConDefs.prodInfo[p].index+j-1]] ¬ table[i]; i ¬ i+1; NPGSConDefs.tEntries ¬ NPGSConDefs.tEntries+1 }; 1 => { j, p: CARDINAL; [,j,p] ¬ table[i]; conflicts[NPGSConDefs.rhsChar[NPGSConDefs.prodInfo[p].index+j-1]] ¬ table[i]; i ¬ i+1; NPGSConDefs.tEntries ¬ NPGSConDefs.tEntries+1 }; 2 => i ¬ i+1; 3 => {conflicts[table[i].pss] ¬ table[i+1]; i ¬ i+2; NPGSConDefs.ntEntries ¬ NPGSConDefs.ntEntries+1}; ENDCASE; ENDLOOP; conflictFlag ¬ FALSE; maxRedEntries ¬ defaultProd ¬ 0; FOR i IN [stateInfo[six].entries..stateInfo[six+1].entries) WHILE table[i].tag = 2 DO IF (k ¬ Find[six,[0,table[i].jf,table[i].pss]]) = rlim THEN { rlim ¬ rlim +1; Context[k,1] }; reduceFlag ¬ FALSE; redEntries ¬ 0; FOR j IN [1..NPGSConDefs.eofMark] DO IF NPGSConDefs.FindBit[bitString,k,j] THEN { IF conflicts[j] = [0,0,0] THEN { conflicts[j] ¬ table[i]; NPGSConDefs.tEntries ¬ NPGSConDefs.tEntries+1; redEntries ¬ redEntries+1 } ELSE { --we have conflicts LalrHeader[]; IF ~reduceFlag THEN { reduceFlag ¬ TRUE; NPGSConDefs.outstring[" REDUCE with "]; NPGSConDefs.outnum[table[i].pss,4]; NPGSConDefs.outstring[" conflicts with "]; NPGSConDefs.outchar[' ,40]; NPGSConDefs.outchar['*,10]; lineWidth ¬ NPGSConDefs.outbufLim }; IF (lineWidth ¬ lineWidth+NPGSConDefs.tokenSize+7) > NPGSConDefs.outbufLim THEN { NPGSConDefs.outeol[1]; NPGSConDefs.outchar[' ,4]; lineWidth ¬ NPGSConDefs.tokenSize+11 }; NPGSConDefs.outchar[' ,NPGSConDefs.tokenSize-NPGSConDefs.OutToken[j]]; IF conflicts[j].tag # 2 THEN { NPGSConDefs.outstring[" SCAN/ "]; NPGSConDefs.warningsLogged ¬ TRUE } ELSE { NPGSConDefs.outnum[conflicts[j].pss,5]; NPGSConDefs.outstring["/ "]; lalrSuccess ¬ FALSE; IF NPGSConDefs.flags[lists] THEN { -- turn off binary output NPGSConDefs.flags[lists] ¬ FALSE; NPGSConDefs.closewordstream[] } } } }; ENDLOOP; IF reduceFlag THEN NPGSConDefs.outeol[1]; IF redEntries > maxRedEntries THEN { maxRedEntries ¬ redEntries; defaultProd ¬ table[i].pss }; ENDLOOP; IF NPGSConDefs.flags[printLALR] THEN LalrHeader[]; IF NPGSConDefs.flags[lists] THEN { NPGSConDefs.outword[defaultProd]; NPGSConDefs.outword[NPGSConDefs.tEntries+NPGSConDefs.ntEntries-oldEntries]; oldEntries ¬ NPGSConDefs.tEntries+NPGSConDefs.ntEntries }; lineWidth ¬ 0; -- New for CUSP: IF cusp THEN { NPGSConDefs.CuspPreClearTokensUsedArray[]; [,j,k] ¬ table[stateInfo[six].nucleus]; IF k > 0 THEN NPGSConDefs.CuspPreSetHeaderUsed[NPGSConDefs.rhsChar[NPGSConDefs.prodInfo[k].index+j-1]]; }; -- end of new stuff FOR j IN [1..NPGSConDefs.totalTokens] DO IF conflicts[j] # [0,0,0] THEN { item: NPGSTypes.ItemRec ¬ conflicts[j]; IF NPGSConDefs.flags[lists] THEN { NPGSConDefs.outword[j]; NPGSConDefs.outword[IF item.tag=0 THEN 0 ELSE 4*item.jf+item.tag]; NPGSConDefs.outword[item.pss] }; IF NPGSConDefs.flags[printLALR] OR conflictFlag THEN { IF item.tag = 2 THEN {item.tag ¬ 1; PrintEntry[item,j,'*]} ELSE PrintEntry[item,j] }; IF cusp THEN NPGSConDefs.CuspPreSetNextTokenUsed[j]; -- new for CUSP }; ENDLOOP; IF cusp THEN NPGSConDefs.CuspPreSetNextErrorMsgElement[six]; -- new for CUSP ENDLOOP; NPGSConDefs.seterrstream[]; NPGSConDefs.outstring["\nLALR(1) Statistics"]; NPGSConDefs.outstring["\nStates ="]; NPGSConDefs.outnum[NPGSConDefs.sLim-1, 4]; NPGSConDefs.outstring["\nTerminal entries ="]; NPGSConDefs.outnum[NPGSConDefs.tEntries, 5]; NPGSConDefs.outstring["\nNonterminal entries ="]; NPGSConDefs.outnum[NPGSConDefs.ntEntries, 5]; NPGSConDefs.outstring["\nFirst OR operation count ="]; NPGSConDefs.outnum[firstOrCount, 5]; NPGSConDefs.outstring["\nTotal OR operation count ="]; NPGSConDefs.outnum[NPGSConDefs.orCount, 5]; NPGSConDefs.outstring["\nMaximum number of contexts ="]; NPGSConDefs.outnum[rlim-1, 5]; NPGSConDefs.outeol[1]; conflicts ¬ NIL; chainStack ¬ NIL; stack ¬ NIL; bitString ¬ NIL; bitsInfo ¬ NIL; firstBits ¬ NIL; backChain ¬ NIL; table ¬ NIL; stateInfo ¬ NIL; NPGSConDefs.rhsChar ¬ NIL; NPGSConDefs.tokenInfo ¬ NIL; hashHead ¬ NIL; RETURN[lalrSuccess] }; ProcessState: PROC = { k1, k2, nmark, entrymark: CARDINAL; -- indexes into table p, j, n: CARDINAL; sym, nsym: CARDINAL; Sort: PROC[index: CARDINAL] = { k1, k2: CARDINAL; item: NPGSTypes.ItemRec; noswap: BOOL; Compare: PROC RETURNS[BOOL] = INLINE { RETURN[table[k1+1].pss > table[k1+3].pss OR (table[k1+1].pss = table[k1+3].pss AND table[k1+1].jf > table[k1+3].jf)] }; FOR k2 ¬ entryLim-2, k2-2 WHILE k2>=index DO noswap ¬ TRUE; FOR k1 ¬ index, k1+2 WHILE k1 table[k1+2].pss OR table[k1].pss = table[k1+2].pss AND Compare[]) THEN { item ¬ table[k1]; table[k1] ¬ table[k1+2]; table[k1+2] ¬ item; item ¬ table[k1+1]; table[k1+1] ¬ table[k1+3]; table[k1+3] ¬ item; noswap ¬ FALSE }; ENDLOOP; IF noswap THEN RETURN; ENDLOOP }; ExpandTable: PROC = { new: NPGSTypes.Table ~ NPGSConDefs.MakeTable[table.length+NPGSConDefs.tabExt]; FOR i: CARDINAL IN [0..entryLim) DO new[i] ¬ table[i] ENDLOOP; FOR i: CARDINAL IN (stateInfo[NPGSConDefs.sLim].nucleus..table.length) DO new[i+NPGSConDefs.tabExt] ¬ table[i] ENDLOOP; FOR i: CARDINAL IN [1..NPGSConDefs.sLim] DO stateInfo[i].nucleus ¬ stateInfo[i].nucleus+NPGSConDefs.tabExt ENDLOOP; table ¬ new }; LocateState: PROC[index, n: CARDINAL] RETURNS[CARDINAL] = { i, j, k, r: CARDINAL; IF table[index+1] = [0,1,0] THEN RETURN[0]; -- final state, n=2 in this case r ¬ (63*n+LOOPHOLE[table[index+1], CARD16]) MOD hashHead­.LENGTH; FOR i ¬ hashHead[r], stateInfo[i].link WHILE i # 0 DO IF n = 2*(stateInfo[i].nucleus-stateInfo[i+1].nucleus) THEN { k ¬ index+1; FOR j DECREASING IN (stateInfo[i+1].nucleus..stateInfo[i].nucleus] DO IF table[j] # table[k] THEN EXIT; k ¬ k+2; REPEAT FINISHED => RETURN[i] ENDLOOP }; ENDLOOP; IF hashHead[r] # 0 THEN stateInfo[NPGSConDefs.sLim].link ¬ hashHead[r]; hashHead[r] ¬ NPGSConDefs.sLim; IF NPGSConDefs.sLim+1 = stateInfo.length THEN stateInfo ¬ NPGSConDefs.ExpandStateInfo[stateInfo, NPGSConDefs.stateExt]; IF entryLim+n/2 > stateInfo[NPGSConDefs.sLim].nucleus THEN ExpandTable[]; r ¬ stateInfo[NPGSConDefs.sLim].nucleus; FOR i ¬ index+1, i+2 WHILE i stateInfo[NPGSConDefs.sLim].nucleus-entryLim+1 THEN ExpandTable[]; FOR k1 DECREASING IN (stateInfo[six+1].nucleus..k1] DO table[entryLim+1] ¬ table[k1]; entryLim ¬ entryLim+2 ENDLOOP; entrymark ¬ entryLim; FOR k2 ¬ stateInfo[six].entries, k2+2 WHILE k2NPGSConDefs.eofMark THEN { -- nonterminal scan t: NPGSTypes.TokenEntry = NPGSConDefs.tokenInfo[sym-NPGSConDefs.eofMark]; FOR p IN [t.index..t.index+t.count) DO FOR k1 ¬ entrymark, k1+2 WHILE k1 { IF entryLim+2 > stateInfo[NPGSConDefs.sLim].nucleus THEN ExpandTable[]; table[entryLim+1] ¬ [0,0,p]; entryLim ¬ entryLim+2 }; ENDLOOP; ENDLOOP } }; ENDLOOP; Sort[stateInfo[six].entries]; IF NPGSConDefs.flags[chain] THEN { -- extend closure k2 ¬ stateInfo[six].entries; WHILE k2 < entryLim AND table[k2].pss <= NPGSConDefs.eofMark DO k2 ¬ k2+2 ENDLOOP; IF k2 < entryLim THEN { entrymark ¬ k2; --first nonterminal entry WHILE k2 < entryLim DO p ¬ table[k2+1].pss; IF NPGSConDefs.prodInfo[p].chain THEN { sym ¬ table[k2].pss; nsym ¬ NPGSConDefs.prodInfo[p].lhs; -- now search for lhs entry k1 ¬ entrymark; WHILE nsym # table[k1].pss DO k1 ¬ k1+2 ENDLOOP; table[k2+1] ¬ table[k1+1]; k2 ¬ k2-2; -- back up k2 in case first chained entry is also a chain entry FOR k1 ¬ k1+2, k1+2 WHILE k1 < entryLim DO IF nsym = table[k1].pss THEN { IF entryLim+2 > stateInfo[NPGSConDefs.sLim].nucleus THEN ExpandTable[]; table[entryLim].pss ¬ sym; table[entryLim+1] ¬ table[k1+1]; entryLim ¬ entryLim+2 }; ENDLOOP }; k2 ¬ k2+2; ENDLOOP; Sort[entrymark] } }; k1 ¬ k2 ¬ stateInfo[six].entries; WHILE k2 < entryLim AND table[k2].pss = 0 DO table[k1] ¬ table[k2+1]; table[k1].tag ¬ 2; k1 ¬ k1+1; k2 ¬ k2+2 ENDLOOP; entrymark ¬ k2; nmark ¬ 0; WHILE entrymark < entryLim DO jf: CARDINAL ¬ 0; k2 ¬ entrymark+2; WHILE k2 < entryLim AND table[k2].pss = table[entrymark].pss DO jf ¬ table[k2+1].jf; table[k2+1].jf ¬ jf+1; k2 ¬ k2+2 ENDLOOP; jf ¬ table[entrymark+1].jf; table[entrymark+1].jf ¬ jf + 1; n ¬ k2-entrymark; -- 2*number of elements in this state IF n#2 OR table[entrymark+1].jf # NPGSConDefs.prodInfo[table[entrymark+1].pss].count THEN table[entrymark+1] ¬ [0,1,LocateState[entrymark,n]] -- make shift ELSE table[entrymark+1].tag ¬ 1; -- make scan reduce IF table[entrymark].pss > NPGSConDefs.eofMark THEN { -- insert symbol IF nmark = 0 THEN nmark ¬ k1; table[k1] ¬ [3,0,table[entrymark].pss]; k1 ¬ k1+1 }; table[k1] ¬ table[entrymark+1]; k1 ¬ k1+1; --insert shift or scan reduce entrymark ¬ k2; ENDLOOP; entryLim ¬ k1 }; -- entryLim-1 => last entry, nmark => first nonterminal entry or is 0 FirstSet: PROC = { i, j, top, listindex: CARDINAL; discrim, vertices: NPGSTypes.AttrVec; t: NPGSTypes.TokenEntry; p: NPGSTypes.ProdEntry; First: PROC[nonterm: CARDINAL] = { prix, chix, w: CARDINAL; discrim[nonterm] ¬ top ¬ top+1; vertices[top] ¬ nonterm; t ¬ NPGSConDefs.tokenInfo[nonterm]; FOR prix IN [t.index..t.index+t.count) DO p ¬ NPGSConDefs.prodInfo[prix]; FOR chix IN [p.index..p.index+p.count) DO w ¬ NPGSConDefs.rhsChar[chix]; IF w <= NPGSConDefs.eofMark THEN {NPGSConDefs.InsertBit[firstBits, nonterm, w]; EXIT}; w ¬ w-NPGSConDefs.eofMark; IF discrim[w] = 0 THEN First[w]; IF discrim[w] <= top THEN discrim[nonterm] ¬ MIN[discrim[nonterm], discrim[w]] ELSE NPGSConDefs.OrBits[firstBits, vertices[discrim[w]], firstBits, nonterm]; IF ~NPGSConDefs.tokenInfo[w].empty THEN EXIT; ENDLOOP; ENDLOOP; IF nonterm = vertices[discrim[nonterm]] THEN { listindex ¬ listindex-1; w ¬ vertices[top]; top ¬ top-1; discrim[w] ¬ listindex; WHILE w # nonterm DO NPGSConDefs.OrBits[firstBits, w, firstBits, nonterm]; w ¬ vertices[top]; top ¬ top-1; discrim[w] ¬ listindex; ENDLOOP; vertices[listindex] ¬ nonterm } }; discrim ¬ NPGSConDefs.MakeAttrVec[NPGSConDefs.totalTokens-NPGSConDefs.eofMark+1]; vertices ¬ NPGSConDefs.MakeAttrVec[NPGSConDefs.totalTokens-NPGSConDefs.eofMark+1]; listindex ¬ NPGSConDefs.totalTokens-NPGSConDefs.eofMark+1; top ¬ 0; -- initialise stack and list of heads FOR i IN [1..NPGSConDefs.totalTokens-NPGSConDefs.eofMark] DO IF discrim[i] = 0 THEN First[i] ENDLOOP; FOR i IN [1..NPGSConDefs.totalTokens-NPGSConDefs.eofMark] DO -- copy head bitStrings to other scc vertices IF i # vertices[discrim[i]] THEN NPGSConDefs.OrBits[firstBits, vertices[discrim[i]], firstBits, i]; ENDLOOP; discrim ¬ NIL; vertices ¬ NIL; IF NPGSConDefs.flags[first] THEN { NPGSConDefs.setoutstream[".first"]; NPGSConDefs.outstring["\nFIRST SETS\n\n"]; FOR i IN [1..NPGSConDefs.totalTokens-NPGSConDefs.eofMark] DO [] ¬ NPGSConDefs.OutToken[i+NPGSConDefs.eofMark]; lineWidth ¬ NPGSConDefs.outbufLim; FOR j IN [1..NPGSConDefs.eofMark] DO IF NPGSConDefs.FindBit[firstBits,i,j] THEN { IF (lineWidth ¬ lineWidth+NPGSConDefs.tokenSize+1) > NPGSConDefs.outbufLim THEN { NPGSConDefs.outeol[1]; NPGSConDefs.outchar[' ,4]; lineWidth ¬ NPGSConDefs.tokenSize+5 }; NPGSConDefs.outchar[' ,NPGSConDefs.tokenSize+1-NPGSConDefs.OutToken[j]] }; ENDLOOP; NPGSConDefs.outeol[2]; ENDLOOP; NPGSConDefs.closeoutstream[] } }; Find: PROC[state: CARDINAL, item: NPGSTypes.ItemRec] RETURNS[CARDINAL] = { i, r: CARDINAL; r ¬ (state + LOOPHOLE[item, CARD16]) MOD hashHead­.LENGTH; i ¬ hashHead[r]; WHILE i # 0 DO IF state = bitsInfo[i].state AND item = bitsInfo[i].item THEN RETURN[i]; i ¬ bitsInfo[i].link; ENDLOOP; IF rlim>=bitsInfo.length THEN { bitsInfo ¬ NPGSConDefs.ExpandBitsInfo[bitsInfo, bitsInfo.length/8]; bitString ¬ NPGSConDefs.ExpandBitString[bitString, bitString.length/8]; }; IF hashHead[r] # 0 THEN bitsInfo[rlim].link ¬ hashHead[r]; hashHead[r] ¬ rlim; bitsInfo[rlim].state ¬ state; bitsInfo[rlim].item ¬ item; RETURN[rlim]; }; Context: PROC[index, base: CARDINAL] = { jf: CARDINAL[0..15] ¬ 0; pss: CARDINAL[0..NPGSTypes.pssLim] ¬ 0; tempItem: NPGSTypes.ItemRec ¬ NPGSTypes.nullItemRec; cj, j: CARDINAL; -- displacements relative to base into chainStack i: CARDINAL; -- used locally but also indexes current (q,k+1) across recursive calls k: CARDINAL; -- used locally but also indexes current state across recursive calls top ¬ top+1; IF top = stack.length THEN stack ¬ NPGSConDefs.ExpandStack[stack, 15]; bitsInfo[index].status ¬ top; stack[top] ¬ index; -- initialise for transitive closure j ¬ bitsInfo[index].item.jf; -- want the jth predecessor state IF base+MAX[1,j] >= chainStack.length THEN chainStack ¬ NPGSConDefs.ExpandStack[chainStack, 45]; cj ¬ 1; chainStack[base+cj] ¬ stateInfo[bitsInfo[index].state].link; --index 1st predec DO -- for each jth predecessor state IF j=0 THEN { predState ¬ bitsInfo[index].state; -- zeroth predecessor j ¬ 1; chainStack[base+cj] ¬ 0 } --ensure no more zeroth predecessors ELSE DO IF chainStack[base+cj] = 0 THEN { IF (cj ¬ cj-1) =0 THEN GOTO quit } -- no more jth predecessors ELSE { [predState, chainStack[base+cj]] ¬ backChain[chainStack[base+cj]]; IF cj=j THEN EXIT; cj ¬ cj+1; chainStack[base+cj] ¬ stateInfo[predState].link }; ENDLOOP; FOR i IN [stateInfo[predState].entries..stateInfo[predState+1].entries) DO IF table[i] = [3,0,NPGSConDefs.prodInfo[bitsInfo[index].item.pss].lhs] THEN EXIT; REPEAT FINISHED => ERROR -- nonterminal not found ENDLOOP; i ¬ i+1; -- index the associated item IF table[i].tag # 0 THEN k ¬ i-1 ELSE { temp: CARDINAL ¬ table[i].pss; k ¬ stateInfo[temp+1].nucleus; i ¬ stateInfo[temp].nucleus }; FOR i DECREASING IN (k..i] DO --select each (q,k+1) s.t. X[q,k+1] = A[p] FOR k IN [table[i].jf..NPGSConDefs.prodInfo[table[i].pss].count) DO --all v s.t. k+2<=v<= n[q] IF (symbol ¬ NPGSConDefs.rhsChar[NPGSConDefs.prodInfo[table[i].pss].index+k]) <= NPGSConDefs.eofMark THEN { NPGSConDefs.InsertBit[bitString, index, symbol]; EXIT } ELSE { symbol ¬ symbol-NPGSConDefs.eofMark; NPGSConDefs.OrBits[firstBits, symbol, bitString, index]; IF ~NPGSConDefs.tokenInfo[symbol].empty THEN EXIT }; REPEAT FINISHED => { jf ¬ table[i].jf; jf ¬ jf-1; pss ¬ table[i].pss; tempItem ¬ [0, jf, pss]; k ¬ Find[predState, tempItem]; IF k = rlim THEN { rlim ¬ rlim+1; Context[k,base+j] }; IF bitsInfo[k].status <= top THEN bitsInfo[index].status ¬ MIN[bitsInfo[index].status, bitsInfo[k].status] ELSE NPGSConDefs.OrBits[bitString, k, bitString, index] }; ENDLOOP; ENDLOOP; REPEAT quit => NULL ENDLOOP; IF index = stack[bitsInfo[index].status] THEN { --scc head k ¬ top; i ¬ stack[top]; bitsInfo[i].status ¬ CARDINAL.LAST; FOR top ¬ top-1, top-1 WHILE i#index DO NPGSConDefs.OrBits[bitString, i, bitString, index]; i ¬ stack[top]; bitsInfo[i].status ¬ CARDINAL.LAST; ENDLOOP; FOR k IN [top+2..k] DO NPGSConDefs.OrBits[bitString, index, bitString, stack[k]]; ENDLOOP }; }; }. P NPGSLALR.mesa Copyright Σ 1985, 1988, 1992 by Xerox Corporation. All rights reserved. Satterthwaite, October 16, 1985 5:47:23 pm PDT Maxwell, August 10, 1983 10:22 am Wyatt, March 21, 1984 10:28:38 am PST Russ Atkinson (RRA) March 14, 1988 5:00:54 pm PST JKF February 6, 1989 11:50:29 am PST variables of the lookahead set calculation make arrays with all entries zeroed the sets of p,j components defining the LR(0) states are built at the end of table; the nucleus field of each state indexes the appropriate set. the entries for states 1,2,... are built at the beginning of table now form inverse of shift transitions for the lookahead sets caculation LALR(1) calculation begins here insert scan and scan reduce entries in conflicts array compute lookaheads, insert reduce entries and output as necessary bitString[k] points at the LALR(1) lookahead for this reduce grab entries for tabgen here procedures called by ProcessState a new state insert new nucleus end of local procedures copy nucleus to entries compute closure now overwrite chain entry with first chained entry now append the other chained entries pack up reduce entries form new states and pack up entries table[entrymark+1].jf _ table[entrymark+1].jf+1; new context locate the (q,k+1) in each jth predecessor state X[q.v]<=eofMark now the core of the transitive closure algorithm Κ—–"cedarcode" style•NewlineDelimiter ™šœ ™ Jšœ Οeœ=™HJšœ/™/Jšœ!™!Jšœ%™%Jšœ1™1Jšœ$™$J™—codešΟk ˜ Kšœ ˜ Kšœ ˜ —K˜šžœžœž˜Kšžœ ˜šžœ˜K˜—K˜K˜K˜K˜Kšœ žœ˜Kšœ žœ˜Kšœ žœΟc˜'KšœžœŸJ˜YK˜!K˜Jšœ*™*Kšœ žœŸ@˜UKšœžœŸ8˜UK˜K˜K˜K˜!K˜K˜K˜K˜š Οnœžœžœžœžœžœ˜3Kšœ>žœ˜GKšœ(žœ˜1Kšœ'žœ˜,K˜K˜š  œžœ˜Kšœžœ˜K˜š žœžœž œžœ4ž˜SK˜šžœžœ˜K˜ZKšžœžœ{˜†K˜—Kšžœ%žœV˜K˜gKšžœ˜—K˜K˜—K˜š  œžœ˜Kšœ"žœžœ˜>Kšœžœ žœ˜šžœžœ˜K˜eK˜—šžœ˜Kšœžœžœ˜*šžœ žœ˜Kšœ žœ žœ$žœ˜IK˜@K˜—K˜.Kšžœ#žœ>˜gK˜†K˜—K˜—K˜š  œžœ˜Kšœžœ˜K˜,Kšœžœ˜=šž˜Kšžœžœ"˜:šžœ˜Kš žœžœžœžœžœ˜8Kš žœžœžœžœ$žœ˜HK˜K˜—Kšž˜—K˜—K˜š  œžœ˜šžœžœ˜KšœžœJ˜\K˜—Kšžœžœžœ˜IK˜—K˜Kšœžœ˜,Jšœ#™#K˜AK˜;Kšœ žœžœ˜-Kšœ\Ÿ ˜iKšœ_Ÿ˜nK˜GJšœS™SJšœ<™šžœž˜K˜!K˜#Kšžœ˜—Kšž˜—Kšžœ˜—Kšžœžœ˜9K˜Kš žœžœžœžœžœ˜RK˜JšœG™GK˜5Kšžœžœžœžœ˜DK˜šžœžœž˜#šžœžœ4ž˜>šžœžœŸ&˜AK˜LK˜)K˜—Kšžœ˜—Kšžœ˜—K˜Jšœ™K˜_K˜oK˜/Kšœ žœŸ˜#K˜GK˜WK˜+K˜'K˜=Kšœžœ˜K˜>Kšžœžœ˜>K˜šžœžœž˜#Kšžœžœžœžœ˜HK˜šžœž˜%Jšœ6™6šžœž˜˜Kšœžœ˜K˜0K˜VK˜-K˜—˜Kšœžœ˜K˜K˜VK˜-K˜—K˜ K˜gKšžœ˜—Kšžœ˜—K˜JšœA™AKšœžœ"˜6šžœžœ4žœžœ˜Všžœ5žœ˜=K˜K˜—Jšœ<™K˜BKšœ ž˜K˜—Kšžœ˜—Kšžœžœžœ˜Kšž˜—K˜—K˜š  œžœ˜K˜Nšžœžœžœž˜#Kšœžœ˜—šžœžœžœ5ž˜IKšœ%žœ˜-—šžœžœžœž˜+Kšœ?žœ˜G—K˜ K˜—K˜š   œžœ žœžœžœ˜;Kšœ žœ˜KšžœžœžœŸ ˜LKš œ žœžœžœ žœ˜Ašžœ$žœž˜5Kšžœ5žœ˜=K˜ šžœž œžœ0ž˜EKšžœžœžœ ˜*Kšžœžœžœ˜Kšž˜—K˜Kšžœ˜—Jšœ ™ KšžœžœP˜gKšžœ'ž˜-K˜IKšžœ4žœ˜IJšœ™K˜(Kšžœžœ žœžœ˜MK˜Ošžœ*žœžœžœ˜RK˜K˜VKšžœ˜K˜—K˜—K˜Jšœ™K˜K˜KšžœRž˜XK˜Jšœ™šžœž œžœ ž˜6Kšœ5žœ˜=—K˜Jšœ™K˜šžœ#žœ ž˜:K˜=šžœ#žœŸ˜:K˜PšžœžœŸ˜5K˜Išžœžœž˜&šžœžœ ž˜-Kšžœžœž˜"šžœžœ˜Kšžœ2žœ˜GK˜2K˜—Kšžœ˜—Kšž˜—K˜—K˜—Kšžœ˜—K˜K˜šžœžœŸ˜5K˜Kšžœžœ&žœ žœ˜Ršžœžœ˜KšœŸ˜)šžœž˜K˜šžœžœ˜'Kšœ9Ÿ˜TKšœžœžœ žœ˜@Jšœ2™2K˜Kšœ Ÿ?˜JJšœ$™$šžœžœž˜*Kšžœžœ˜Kšžœ2žœ˜GK˜;K˜K˜Kšž˜—K˜—K˜ Kšžœ˜—K˜K˜—K˜—K˜Jšœ™K˜!šžœžœž˜,KšœAžœ˜I—K˜Jšœ#™#K˜šžœž˜Kšœžœ˜K˜šžœžœ&ž˜?K˜K˜˜ Kšžœ˜——K˜K˜Jšœ0™0KšœŸ%˜7KšžœžœLž˜Yšœ5Ÿ ˜BKšžœŸ˜4—šžœ,žœŸ˜EKšžœ žœ ˜K˜1K˜—Kšœ+Ÿ˜HK˜Kšžœ˜—K˜ KšœŸE˜H—K˜š œžœ˜Kšœžœ˜K˜%K˜K˜K˜š œžœ žœ˜"Kšœžœ˜K˜8K˜#šžœžœž˜)K˜šžœžœž˜)K˜Kšžœžœ0žœ˜VKšœžœžœ ˜;šžœžœžœ˜NKšžœI˜M—Kšžœ!žœžœ˜-Kšžœ˜—Kšžœ˜—šžœ&žœ˜.K˜K˜7šžœ ž˜K˜5K˜7Kšžœ˜—K˜K˜—K˜—K˜K˜QK˜RKšœDŸ%˜iKš žœžœ2žœžœžœ žœ˜ešžœžœ2žœŸ-˜kKšžœž˜ K˜BKšžœ˜—Kšœ žœ žœ˜šžœžœ˜"K˜Nšžœžœ2ž˜Kšžœžœžœ6˜`KšœEŸ˜WšžœŸ!˜$šžœžœ˜ Kšœ#Ÿ˜8K˜KšœŸ$˜'—Kšž˜šž˜šžœžœ˜!Kšžœžœžœ˜ KšœŸ˜—šžœ˜K˜BKšžœžœžœ˜K˜:K˜—Kšžœ˜—Jšœ0™0šžœžœ@ž˜JKšžœEžœžœ˜QKšžœžœžœŸ˜2Kšžœ˜—Kšœ Ÿ˜%šžœžœ žœ˜'Kšœžœ˜K˜K˜K˜—š žœž œžœžœŸ*˜Hšžœžœ9žœŸ˜^šžœcžœ˜kJšœ™Kšœ1ž˜5K˜—šžœ˜K˜$K˜8Kšžœ&žœž˜1K˜—Jšœ0™0šžœžœ˜K˜K˜ K˜K˜K˜šžœ žœ˜K˜K˜K˜—Kšžœž˜!šœžœ,˜HKšžœ3˜7—K˜—Kšžœ˜—Kšžœ˜—Kšžœ ž˜Kšžœ˜—šžœ'žœŸ ˜:Kšœ.žœžœ˜<šžœžœ ž˜'K˜3Kšœ%žœžœ˜3Kšžœ˜—šžœžœ ž˜K˜:Kšž˜—K˜—K˜—K˜K˜—K˜—…—QjjQ