/* important local variables */
int lastred
; /* the number of the last reduction of a state */
int defact
[NSTATES
]; /* the default actions of states */
output(){ /* print the output for the states */
register struct wset
*u
, *v
;
fprintf( ftable
, "short yyexca[] ={\n" );
SLOOP(i
) { /* output the stuff for state i */
nolook
= !(tystate
[i
]==MUSTLOOKAHEAD
);
aryfil( temp1
, ntokens
+nnonter
+1, 0 );
if( c
>1 && c
<NTBASE
&& temp1
[c
]==0 ) {
if( c
== *(v
->pitem
) ) putitem( v
->pitem
+1, (struct looksets
*)0 );
else if( c
> NTBASE
&& temp1
[ (c
-= NTBASE
) + ntokens
] == 0 ){
temp1
[ c
+ntokens
] = amem
[indgo
[i
]+c
];
if( i
== 1 ) temp1
[1] = ACCEPTCODE
;
/* now, we have the shifts; look at the reductions */
if( c
<=0 ){ /* reduction */
if( temp1
[k
] == 0 ) temp1
[k
] = c
;
else if( temp1
[k
]<0 ){ /* reduce/reduce conflict */
"\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 */
precftn( lastred
, k
, i
);
fprintf( ftable
, "\t};\n" );
wdef( "YYNPROD", nprod
);
apack(p
, n
) int *p
;{ /* pack state i from temp1 into amem */
/* we don't need to worry about checking because we
we will only look entries known to be there... */
/* eliminate leading and trailing 0's */
for( pp
=p
,off
=0 ; *pp
==0 && pp
<=q
; ++pp
,--off
) /* VOID */ ;
if( pp
> q
) return(0); /* no actions */
/* now, find a place for the elements from p to q, inclusive */
for( rr
=amem
; rr
<=r
; ++rr
,++off
){ /* try rr */
for( qq
=rr
,pp
=p
; pp
<=q
; ++pp
,++qq
){
if( *pp
!= *qq
&& *qq
!= 0 ) goto nextk
;
/* we have found an acceptable k */
if( pkdebug
&& foutput
!=NULL
) fprintf( foutput
, "off = %d, k = %d\n", off
, rr
-amem
);
for( qq
=rr
,pp
=p
; pp
<=q
; ++pp
,++qq
){
if( qq
> r
) error( "action table overflow" );
if( pkdebug
&& foutput
!=NULL
){
for( pp
=amem
; pp
<= memp
; pp
+=10 ){
for( qq
=pp
; qq
<=pp
+9; ++qq
) fprintf( foutput
, "%d ", *qq
);
error("no space in action table" );
go2out(){ /* output the gotos for the nontermninals */
int i
, j
, k
, best
, count
, cbest
, times
;
fprintf( ftemp
, "$\n" ); /* mark begining of gotos */
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
){
fprintf( ftemp
, "%d,%d,", j
, tystate
[j
] );
fprintf( ftemp
, "%d\n", best
);
go2gen(c
){ /* output the gotos for nonterminal c */
/* first, find nonterminals with gotos on c */
aryfil( temp1
, nnonter
+1, 0 );
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 */
if( g2debug
&& foutput
!=NULL
){
fprintf( foutput
, "%s: gotos on ", nontrst
[c
].name
);
NTLOOP(i
) if( temp1
[i
] ) fprintf( foutput
, "%s ", nontrst
[i
].name
);
/* now, go through and put gotos into tystate */
aryfil( tystate
, nstate
, 0 );
if( (cc
= *p
->pitem
) >= NTBASE
){
if( temp1
[cc
-= NTBASE
] ){ /* goto on c is possible */
tystate
[i
] = amem
[indgo
[i
]+c
];
precftn(r
,t
,s
){ /* decide a shift/reduce conflict by precedence.
/* r is a rule number, t a token number */
/* the conflict is in state s */
/* temp1[t] is changed to reflect the action */
if( PLEVEL(lt
) == 0 || PLEVEL(lp
) == 0 ) {
if( foutput
!= NULL
) fprintf( foutput
, "\n%d: shift/reduce conflict (shift %d, red'n %d) on %s",
s
, temp1
[t
], r
, symnam(t
) );
if( PLEVEL(lt
) == PLEVEL(lp
) ) action
= ASSOC(lt
);
else if( PLEVEL(lt
) > PLEVEL(lp
) ) action
= RASC
; /* shift */
else action
= LASC
; /* reduce */
case BASC
: /* error action */
wract(i
){ /* output state i */
/* temp1 has the actions, lastred the default */
int ntimes
, tred
, count
, j
;
/* find the best choice for lastred */
if( temp1
[j
] >= 0 ) continue;
if( temp1
[j
]+lastred
== 0 ) continue;
/* count the number of appearances of temp1[j] */
if( temp1
[p
]+tred
== 0 ) ++count
;
/* for error recovery, arrange that, if there is a shift on the
/* error recovery token, `error', that the default be the error action */
if( temp1
[1] > 0 ) lastred
= 0;
/* clear out entries in temp1 which equal lastred */
TLOOP(p
) if( temp1
[p
]+lastred
== 0 )temp1
[p
]=0;
if( (p1
=temp1
[p0
])!=0 ) {
else if( p1
== ACCEPTCODE
) {
else if( p1
== ERRCODE
) {
if( flag
++ == 0 ) fprintf( ftable
, "-1, %d,\n", i
);
fprintf( ftable
, "\t%d, %d,\n", tokset
[p0
].value
, p1
);
fprintf( ftemp
, "%d,%d,", tokset
[p0
].value
, p1
);
fprintf( ftable
, "\t-2, %d,\n", lastred
);
wrstate(i
){ /* writes state i */
register struct item
*pp
, *qq
;
if( foutput
== NULL
) return;
fprintf( foutput
, "\nstate %d\n",i
);
ITMLOOP(i
,pp
,qq
) fprintf( foutput
, "\t%s\n", writem(pp
->pitem
));
if( tystate
[i
] == MUSTLOOKAHEAD
){
/* print out empty productions in closure */
WSLOOP( wsets
+(pstate
[i
+1]-pstate
[i
]), u
){
if( *(u
->pitem
) < 0 ) fprintf( foutput
, "\t%s\n", writem(u
->pitem
) );
/* check for state equal to another */
TLOOP(j0
) if( (j1
=temp1
[j0
]) != 0 ){
fprintf( foutput
, "\n\t%s ", symnam(j0
) );
if( j1
>0 ){ /* shift, error, or accept */
if( j1
== ACCEPTCODE
) fprintf( foutput
, "accept" );
else if( j1
== ERRCODE
) fprintf( foutput
, "error" );
else fprintf( foutput
, "shift %d", j1
);
else fprintf( foutput
, "reduce %d",-j1
);
/* output the final production */
if( lastred
) fprintf( foutput
, "\n\t. reduce %d\n\n", lastred
);
else fprintf( foutput
, "\n\t. error\n\n" );
/* now, output nonterminal actions */
for( j0
= 1; j0
<= nnonter
; ++j0
){
if( temp1
[++j1
] ) fprintf( foutput
, "\t%s goto %d\n", symnam( j0
+NTBASE
), temp1
[j1
] );
wdef( s
, n
) char *s
; { /* output a definition of s to the value n */
fprintf( ftable
, "# define %s %d\n", s
, n
);
warray( s
, v
, n
) char *s
; int *v
, n
; {
fprintf( ftable
, "short %s[]={\n", s
);
if( i
%10 == 0 ) fprintf( ftable
, "\n" );
fprintf( ftable
, "%4d", v
[i
] );
if( ++i
== n
) fprintf( ftable
, " };\n" );
else fprintf( ftable
, "," );
/* in order to free up the mem and amem arrays for the optimizer,
/* and still be able to output yyr1, etc., after the sizes of
/* the action array is known, we hide the nonterminals
/* derived by productions in levprd.
if( !(levprd
[i
] & REDFLAG
) ){
fprintf( foutput
, "Rule not reduced: %s\n", writem( prdptr
[i
] ) );
levprd
[i
] = *prdptr
[i
] - NTBASE
;
if( j
) fprintf( stdout
, "%d rules never reduced\n", j
);