static char *sccsid
= "@(#)ey4.c 4.2 (Berkeley) 8/30/82";
/* (c) 1979 Regents of the University of California */
output(){ /* print the output for the states */
for( i
=0; i
<nstate
; ++i
){ /* output the stuff for state i */
nolook
= (tystate
[i
]==0);
aryfil( temp1
, nterms
+1, 0 );
for( j
=0; j
<cwset
; ++j
){ /* look at the items */
if( c
>0 && c
<NTBASE
&& temp1
[c
]==0 ) temp1
[c
] = go2(i
,c
);
if( i
== 1 ) temp1
[1] = ACCEPTCODE
;
/* now, we have the shifts; look at the reductions */
for( j
=0; j
<cwset
; ++j
){
if( c
<=0 ){ /* reduction */
for( k
=1; k
<=nterms
; ++k
){
if( ((wsets
[j
].ws
[k
>>4])&(1<<(k
&017))) != 0 ) {
if( temp1
[k
] == 0 ) temp1
[k
] = c
;
else if( temp1
[k
]<0 ){ /* reduce/reduce conflict */
fprintf( cout
, "\n%d: reduce/reduce conflict (red'ns %d and %d ) on %s",
i
, -temp1
[k
], lastred
, symnam(k
) );
if( -temp1
[k
] > lastred
) temp1
[k
] = -lastred
;
else { /* potential shift/reduce conflict */
switch( precftn( lastred
, k
) ) {
case 0: /* precedence does not apply */
fprintf( cout
, "\n%d: shift/reduce conflict (shift %d, red'n %d) on %s", i
,
temp1
[k
], lastred
, symnam(k
) );
/* resolve in favor of shifting, so remove from reduce set */
wsets
[j
].ws
[k
>>4] &=~ (1<<(k
&017));
case 2: /* error, binary operator */
case 3: /* shift ... leave the entry alone */
/* now, output the pointers to the action array */
/* also output the info about reductions */
prred(){ /* print the information about the actions and the reductions */
index
= 1; /* position in the output table */
for( i
=0; i
<nstate
; ++i
){
if( tystate
[i
]>0 ){ /* the state is real */
arrval( temp1
[-tystate
[i
]] );
for( i
=1; i
<nprod
; ++i
) arrval( *prdptr
[i
] - NTBASE
);
for( i
=1; i
<nprod
; ++i
) arrval( ( prdptr
[i
+1]-prdptr
[i
]-2 ) );
go2(i
,c
){ /* do a goto on the closure state, not worrying about lookaheads */
if( c
<NTBASE
) return( amem
[ apstate
[i
]+c
] );
else return( amem
[ apstate
[i
] + c
- NTBASE
+ nterms
] );
apack(p
, n
) int *p
;{ /* pack state i from temp1 into amem */
for( off
= 0; off
<= j
&& p
[off
] == 0; ++off
) ;
if( off
> j
){ /* no actions */
for( k
=0; k
<actsiz
; ++k
){
if( p
[off
+l
] != amem
[k
+l
] && amem
[k
+l
] != 0 ) goto nextk
;
if( pkdebug
){ settty(); fprintf( cout
, "off = %d, k = %d\n", off
, k
); }
/* we have found an acceptable k */
if( k
+l
>= actsiz
) error("action table overflow");
if( k
+l
>= memact
) memact
= k
+l
;
for( k
=0; k
<memact
; k
+=10){
for( l
=0; l
<=9; ++l
) fprintf( cout
, "%d ", amem
[k
+l
] );
error("no space in action table");
go2out(){ /* output the gotos for the nontermninals */
int i
, j
, k
, best
, offset
, count
, cbest
, times
;
for( i
=1; i
<=nnonter
; ++i
) {
/* find the best one to make default */
for( j
=0; j
<=nstate
; ++j
){ /* is j the most frequent */
if( tystate
[j
] == 0 ) continue;
if( tystate
[j
] == best
) continue;
/* is tystate[j] the most frequent */
for( k
=j
; k
<=nstate
; ++k
) if( tystate
[k
]==cbest
) ++count
;
/* best is now the default entry */
for( j
=0; j
<=nstate
; ++j
){
if( tystate
[j
] != 0 && tystate
[j
]!=best
){
for( i
=1; i
<=nnonter
; ++i
) arrval( temp2
[i
] );
go2gen(c
){ /* output the gotos for nonterminal c */
/* first, find nonterminals with gotos on c */
aryfil( temp1
, nnonter
+1, 0 );
for( i
=0; i
<nprod
; ++i
){
if( (cc
=prdptr
[i
][1]-NTBASE
) >= 0 ){ /* cc is a nonterminal */
if( temp1
[cc
] != 0 ){ /* cc has a goto on c */
cc
= *prdptr
[i
]-NTBASE
; /* thus, the left side of production i does too */
/* now, we have temp1[c] = 1 if a goto on c in closure of cc */
fprintf( cout
, "%s: gotos on ", nontrst
[c
].name
);
for( i
=0; i
<=nnonter
; ++i
) if( temp1
[i
]) fprintf( cout
, "%s ", nontrst
[i
].name
);
/* now, go through and put gotos into tystate */
aryfil( tystate
, nstate
, 0 );
fprintf( cout
, "\nnonterminal %s\n", nontrst
[c
].name
);
for( i
=0; i
<nstate
; ++i
){
for( p
=pstate
[i
]; p
<q
; ++p
){
if( (cc
= *p
->pitem
) >= NTBASE
){
if( temp1
[cc
-= NTBASE
] ){ /* goto on c is possible */
tystate
[i
] = amem
[indgo
[i
]+c
];
if( tystate
[i
] ) fprintf( cout
, "\t%d\t%d\n", i
, tystate
[i
]);
precftn(r
,t
){ /* decide a shift/reduce conflict by precedence.
Returns 0 if action is 'do nothing',1 if action is reduce,
2 if the action is 'error,binary operator'
and 3 if the action is 'reduce'. */
if ((lt
==0)||((lp
&03)==0))return(0);
if((lt
>>3) > (lp
>>3)) return(3);
int cdebug
= 0; /* debug for common states */
wract(i
){ /* output state i */
/* temp1 has the actions, lastred the default */
int ntimes
, tred
, count
, j
, k
;
/* find the best choice for lastred */
/***** UCB MOD - full state spec if shift on error *****/
stateflags
[i
] |= NEEDSREDUCE
;
else for( j
=1; j
<=nterms
; ++j
){
/* find the entry on which the greatest number of reductions are done */
if( temp1
[j
] >= 0 ) continue;
if( temp1
[j
]+lastred
== 0 ) continue;
/* count the number of appearances of temp1[j] */
for( p
=1; p
<=nterms
; ++p
){
if( temp1
[p
]+tred
== 0 ) ++count
;
/* clear out entries in temp1 which equal lastred */
/* ie, make the most frequent reduction into the default reduction */
for( p
=1; p
<= nterms
; ++p
) if( temp1
[p
]+lastred
== 0 )temp1
[p
]=0;
/* write out the state */
/* first, check for equality with another state */
/* see if there is a nonterminal with all dots before it, */
/* and no reductions in the state */
/* this is done by checking if all items are the same non-terminal */
for( q0
=pstate
[i
]; q0
<q1
; ++q0
){
if( (p1
= *(q0
->pitem
) ) < NTBASE
) goto standard
;
else if( p0
!= p1
) goto standard
;
stateflags
[i
] |= SINGLE_NT
| pempty
[p0
- NTBASE
];
/* now, all items have dots before p0 */
fprintf( cout
, "state %d, pre-nonterminal %s\n",i
,nontrst
[p0
-NTBASE
].name
);
* check that the states have the same shift lookaheads.
if( apstate
[i
] != apstate
[j
] )
fprintf(cout
, "states %d and %d have same shift lookaheads\n",i
,j
);
* Check that state has one item, and that the item matches.
if ((stateflags
[j
] & SINGLE_NT
) == 0 || *(pstate
[j
]->pitem
) != p0
)
* Check that enumeration and reduce lookaheads are the same.
if ((stateflags
[i
]&(GENLAMBDA
|NEEDSREDUCE
)) == (GENLAMBDA
|NEEDSREDUCE
)) {
* state[i] needs full reduce lookahead
* state[j] has full reduce lookahead
if ((stateflags
[j
] & NEEDSREDUCE
) == 0)
error("state %d does not need full reduce", j
);
error("missing lambda rule definition in state %d", i
);
error("state %d lookahead was not saved", j
);
/* must check lookaheads */
for (k
= 0; k
< tbitset
; ++k
)
if (lastate
[lookstate
[j
]].lset
[k
] != wsets
[lambdarule
].ws
[k
])
/* cannot merge states */ goto nextj
;
/* we have a match with state j ! */
fprintf( cout
, "state %d matches state %d\n", i
, j
);
/* merged, so no need for future consideration */
if ((stateflags
[i
] & (SINGLE_NT
|NEEDSREDUCE
|GENLAMBDA
)) ==
(SINGLE_NT
|NEEDSREDUCE
|GENLAMBDA
)) {
if (savedlook
+ 1 >= maxlastate
) {
"Warning: _maxlastate too small (%d), state packing impared\n",
/* cannot consider future merger with this state */
fprintf( cout
, "save lookahead for state %d\n", i
);
lookstate
[i
] = savedlook
;
for (k
= 0; k
< tbitset
; ++k
)
lastate
[savedlook
].lset
[k
] = wsets
[lambdarule
].ws
[k
];
for( p0
=1; p0
<=nterms
; ++p0
)
if( (p1
=temp1
[p0
])!=0 ) {
/***** UCB MOD - test actions are negative of symbol to be tested
this speeds up the parser as it is easy to check for
arrval( -trmset
[p0
].value
);
if( p1
< 0 ) arrval( REDUCACT
- p1
);
else if( p1
== ACCEPTCODE
) arrval( ACCEPTACT
);
else if( p1
== ERRCODE
) arrval( ERRACT
);
else arrval( SHIFTACT
+ p1
);
if( lastred
) arrval( REDUCACT
+ lastred
);
tystate
[i
] = size
+1; /* store entry size in tystate */
wrstate(i
){ /* writes state i */
fprintf( cout
, "\nstate %d\n",i
);
for( pp
=pstate
[i
]; pp
<qq
; ++pp
) fprintf( cout
, "\t%s\n", writem(pp
));
/* check for state equal to another */
fprintf( cout
, "\n\tsame as %d\n\n", -tystate
[i
] );
for( j0
=1; j0
<=nterms
; ++j0
) if( (j1
=temp1
[j0
]) != 0 ){
fprintf( cout
, "\n\t%s ", symnam(j0
) );
if( j1
>0 ){ /* shift, error, or accept */
if( j1
== ACCEPTCODE
) fprintf( cout
, "accept" );
else if( j1
== ERRCODE
) fprintf( cout
, "error" );
else fprintf( cout
, "shift %d", j1
);
else fprintf( cout
, "reduce %d",-j1
);
/* output the final production */
if( lastred
) fprintf( cout
, "\n\t. reduce %d\n\n", lastred
);
else fprintf( cout
, "\n\t. error\n\n" );