Beispiel #1
0
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 );
}
Beispiel #2
0
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 );
}
Beispiel #3
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 );
}