void EliminateUnitReductions( void ) /**********************************/ { unsigned sum; a_word *reduce_set; int i; sum = 0; do { changeOccurred = 0; for( i = 0; i < nstate; ++i ) { tossSingleReduceStates( statetab[i] ); } sum += changeOccurred; } while( changeOccurred ); reduce_set = AllocSet( 1 ); do { changeOccurred = 0; for( i = 0; i < nstate; ++i ) { tryElimination( statetab[i], reduce_set ); } sum += changeOccurred; } while( changeOccurred ); FREE( reduce_set ); dumpstatistic( "unit reduction states removed", deadStates ); dumpstatistic( "unit reduction optimizations", sum ); }
int main( int argc, char **argv ) { int i; FILE *skeleton, *temp, *tokout, *actout; int ch; char tempfname[10]; char *fileprefix = "y"; size_t size; param_requested = 0; for( i = 1; i < argc; ++i ) { ch = argv[i][0]; switch( param_requested ) { case 'b': if( ch != '-' ) { if( ch != '\0' ) fileprefix = argv[i]; ++i; } break; case 'p': if( ch != '-' ) { if( ch != '\0' ) symprefix = argv[i]; ++i; } break; default: break; } param_requested = 0; if( argv[i][0] != '-' ) break; setoptions( &argv[i][1] ); } if( i != argc - 1 && i != argc - 2 ) { puts( "usage: yacc [-dlv] [-d[bcdfhpstuw]] [-b <file_prefix>] [-p <sym_prefix>]" ); puts( " <grammar> [<driver>]" ); puts( "options:" ); puts( " -b <file_prefix> file prefix used in place of default 'y' prefix" ); puts( " -d output header file" ); puts( " -db output bigger (less optimal) tables" ); puts( " -dc output compact tables (slower to execute)" ); puts( " -dd use dense tokens (no '+' style tokens allowed)" ); puts( " -de dump all symbols to header file as enum items, no macros" ); puts( " -df output fast tables (larger size)" ); puts( " -dh use 'default shift' optimization" ); puts( " -dp dump all productions" ); puts( " -ds dump full state tables" ); puts( " -dt translate 'keyword' to Y_KEYWORD, '++' to Y_PLUS_PLUS, etc." ); puts( " -du eliminate useless unit production reduction" ); puts( " -dw disable default action type checking" ); puts( " -l output #line directives" ); puts( " -p <sym_prefix> symbol prefix used in place of default 'yy' prefix" ); puts( " -v write description and report into file" ); exit( 1 ); } skeleton = NULL; if( i == argc - 2 ) { skeleton = openr( argv[argc - 1] ); if( skeleton == NULL ) { msg( "could not open driver source code '%s'\n", argv[argc - 1] ); } } loadpath = argv[0]; *getname( loadpath ) = '\0'; srcname = argv[i]; if( !strrchr( srcname, '.' ) ) { srcname = alloca( strlen( argv[i] )+3 ); srcname = strcat( strcpy( srcname, argv[i] ), ".y" ); } yaccin = openr( srcname ); size = strlen( fileprefix); codefilename = MALLOC( size + 6, char ); strcat( strcpy( codefilename, fileprefix), "tab.c" ); headerfilename = MALLOC( size + 6, char ); strcat( strcpy( headerfilename, fileprefix), "tab.h" ); descfilename = MALLOC( size + 5, char ); strcat( strcpy( descfilename, fileprefix), ".out" ); actout = openw( codefilename ); defs( actout ); tokout = openw( headerfilename ); dump_header( tokout ); temp = NULL; for( i = 0; i < 1000 && temp == NULL; ++i ) { sprintf( tempfname, "ytab.%3d", i ); temp = fopen( tempfname, "w+" ); } if( temp == NULL ) { msg( "Cannot create temporary file\n" ); } rules( temp ); buildpro(); CalcMinSentence(); if( proflag || showflag ) { showpro(); } lr0(); lalr1(); SetupStateTable(); /* apply state filters */ FindUnused(); if( eliminateunitflag ) { EliminateUnitReductions(); } if( default_shiftflag ) { if( keyword_id_low == 0 ) { msg( "No %%keyword_id <low> <high> specified." ); } else { MarkDefaultShifts(); } } MarkNoUnitRuleOptimizationStates(); RemoveDeadStates(); MarkDefaultReductions(); if( showflag ) { showstates(); } if( warnings ) { if( warnings == 1 ) { printf( "%s: 1 warning\n", srcname ); } else { printf( "%s: %d warnings\n", srcname, warnings ); } exit( 1 ); } parsestats(); dumpstatistic( "parser states", nstate ); dumpstatistic( "# states (1 reduce only)", nstate_1_reduce ); dumpstatistic( "reduce/reduce conflicts", RR_conflicts ); dumpstatistic( "shift/reduce conflicts", SR_conflicts ); show_unused(); if( skeleton == NULL ) { skeleton = fpopen( loadpath, "yydriver.c" ); if( skeleton == NULL ) { warn( "Can't find yacc skeleton yydriver.c\n" ); } } /* copy first part of skeleton */ if( skeleton != NULL ) copy_part( skeleton, actout ); rewind( tokout ); /* copy tokens */ copy_rest( tokout, actout ); close_header( tokout ); genobj( actout ); /* copy middle part of skeleton */ if( skeleton != NULL ) copy_part( skeleton, actout ); rewind( temp ); copy_rest( temp, actout ); fclose( temp ); remove( tempfname ); /* copy last part of skeleton */ if( skeleton != NULL ) { copy_rest( skeleton, actout ); fclose( skeleton ); } tail( actout ); fclose( actout ); FREE( codefilename ); FREE( headerfilename ); FREE( descfilename ); return( 0 ); }
void genobj( void ) { value_size token_size; action_n *actions, *parent, *other; base_n *base; token_n *p, *q, *r, *s; token_n *tokens, *same, *diff, *test, *best; set_size *mp; token_n tokval, dtoken, ptoken, ntoken; action_n actval, error, redun, new_action; a_sym *sym; a_pro *pro; an_item *item; a_state *x; a_shift_action *tx; a_reduce_action *rx; index_n i, j; set_size savings, min, *size; set_size shift; token_n parent_base; unsigned num_default, num_parent; if( fastflag ) { GenFastTables(); return; } if( bigflag || compactflag ) { token_size = FITS_A_WORD; } else { token_size = FITS_A_BYTE; } num_default = 0; num_parent = 0; ntoken = FirstNonTerminalTokenValue(); dtoken = ntoken++; ptoken = ntoken++; for( i = nterm; i < nsym; ++i ) { symtab[i]->token = ntoken++; } actions = CALLOC( ntoken, action_n ); error = nstate + npro; for( i = 0; i < ntoken; ++i ) { actions[i] = error; } tokens = CALLOC( ntoken, token_n ); test = CALLOC( ntoken, token_n ); best = CALLOC( ntoken, token_n ); other = CALLOC( nstate, action_n ); parent = CALLOC( nstate, action_n ); size = CALLOC( nstate, set_size ); base = CALLOC( nstate, base_n ); same = NULL; r = NULL; diff = NULL; used = 0; avail = 0; table = NULL; shift = 0; parent_base = 0; for( i = nstate; i > 0; ) { --i; x = statetab[i]; q = tokens; for( tx = x->trans; (sym = tx->sym) != NULL; ++tx ) { *q++ = sym->token; actions[sym->token] = tx->state->sidx; } savings = 0; for( rx = x->redun; (pro = rx->pro) != NULL; ++rx ) { redun = pro->pidx + nstate; mp = Members( rx->follow ); if( (set_size)( mp - setmembers ) > savings ) { savings = (set_size)( mp - setmembers ); r = q; } while( mp != setmembers ) { --mp; tokval = symtab[*mp]->token; *q++ = tokval; actions[tokval] = redun; } } if( savings ) { actval = actions[*r]; other[i] = actval; *q++ = dtoken; actions[dtoken] = actval; p = r; while( savings-- > 0 ) actions[*p++] = error; while( p < q ) *r++ = *p++; q = r; ++num_default; } else { other[i] = error; } r = q; min = (set_size)( q - tokens ); size[i] = min; parent[i] = nstate; for( j = nstate; --j > i; ) { if( abs( size[j] - size[i] ) < min ) { x = statetab[j]; p = test; q = test + ntoken; for( tx = x->trans; (sym = tx->sym) != NULL; ++tx ) { if( actions[sym->token] == tx->state->sidx ) { *p++ = sym->token; } else { *--q = sym->token; } } for( rx = x->redun; (pro = rx->pro) != NULL; ++rx ) { redun = pro->pidx + nstate; if( redun == other[j] ) redun = error; for( mp = Members( rx->follow ); mp != setmembers; ) { --mp; tokval = symtab[*mp]->token; if( actions[tokval] == redun ) { *p++ = tokval; } else { *--q = tokval; } } } if( other[j] != error ) { if( other[j] == other[i] ) { *p++ = dtoken; } else { *--q = dtoken; } } savings = (set_size)( size[i] + size[j] - 2 * ( p - test ) ); if( savings < min ) { min = savings; same = p; diff = q; s = test; test = best; best = s; parent[i] = j; } } } if( min >= size[i] ) { s = r; } else { ++num_parent; s = tokens; p = same; while( --p >= best ) actions[*p] = error; for( q = tokens; q < r; ++q ) { if( actions[*q] != error ) { *s++ = *q; } } p = best + ntoken; while( --p >= diff ) { if( actions[*p] == error ) { *s++ = *p; } } actval = parent[i]; *s++ = ptoken; actions[ptoken] = actval; } base[i] = addtotable( tokens, s, actions, dtoken, ptoken ); while( --s >= tokens ) { actions[*s] = error; } } FREE( actions ); FREE( tokens ); FREE( test ); FREE( best ); FREE( other ); FREE( size ); putambigs( base ); putnum( "YYNOACTION", error - nstate + used ); putnum( "YYEOFTOKEN", eofsym->token ); putnum( "YYERRTOKEN", errsym->token ); putnum( "YYETOKEN", errsym->token ); if( compactflag ) { parent_base = used + npro; putnum( "YYPARENT", parent_base ); shift = 8; for( i = 256; i < used; i <<= 1 ) { ++shift; } putnum( "YYPRODSIZE", shift ); } else { putnum( "YYPTOKEN", ptoken ); putnum( "YYDTOKEN", dtoken ); } putnum( "YYSTART", base[startstate->sidx] ); putnum( "YYSTOP", base[eofsym->enter->sidx] ); putnum( "YYERR", base[errstate->sidx] ); putnum( "YYUSED", used ); if( compactflag ) { begtab( "YYPACKTYPE", "yyacttab" ); j = nstate; for( i = 0; i < used; ++i ) { new_action = table[i].action; if( i == base[j - 1] ) { --j; // First element in each state is default/parent if( parent[j] == nstate ) { // No parent state tokval = used + parent_base; } else { tokval = base[parent[j]] + parent_base; } // 0 indicates no default if( new_action != 0 ) { if( new_action < nstate ) { // Shift new_action = base[new_action]; } else { // Reduce new_action -= nstate; // convert to 0 based new_action += used; // now convert to 'used' base } } } else { tokval = table[i].token; if( new_action < nstate ) { // Shift new_action = base[new_action]; } else { // Reduce new_action -= nstate; // convert to 0 based new_action += used; // now convert to 'used' base } } putcompact( tokval, new_action ); } endtab(); // Combine lengths & lhs into a single table begtab( "YYPRODTYPE", "yyprodtab" ); for( i = 0; i < npro; ++i ) { j = 0; for( item = protab[i]->items; item->p.sym != NULL; ++item ) { ++j; } puttab( FITS_A_WORD, (j << shift) + protab[i]->sym->token ); } endtab(); } else { begtab( "YYCHKTYPE", "yychktab" ); for( i = 0; i < used; ++i ) { puttab( token_size, Token( table + i ) ); } endtab(); begtab( "YYACTTYPE", "yyacttab" ); for( i = 0; i < used; ++i ) { j = Action( table + i ); if( j < nstate ) { puttab( FITS_A_WORD, base[j] ); } else { puttab( FITS_A_WORD, j - nstate + used ); } } endtab(); begtab( "YYPLENTYPE", "yyplentab" ); for( i = 0; i < npro; ++i ) { for( item = protab[i]->items; item->p.sym != NULL; ) { ++item; } puttab( FITS_A_BYTE, (unsigned)( item - protab[i]->items ) ); } endtab(); begtab( "YYPLHSTYPE", "yyplhstab" ); for( i = 0; i < npro; ++i ) { puttab( token_size, protab[i]->sym->token ); } endtab(); } FREE( table ); FREE( base ); FREE( parent ); dumpstatistic( "bytes used in tables", bytesused ); dumpstatistic( "states with defaults", num_default ); dumpstatistic( "states with parents", num_parent ); puttokennames( dtoken, token_size ); FREE( protab ); FREE( symtab ); }