genc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 487 行 · 第 1/2 页

C
487
字号
            }
            if( symnum == nsym ) {
                fprintf( actout, "    case %d:\n", token );
            } else if( symtab[symnum]->name[0] == '\'' ) {
                fprintf( actout, "    case %s:\n", symtab[symnum]->name );
            } else {
                fprintf( actout, "    case %d: /* %s */\n", token,
                                    symtab[symnum]->name );
            }
            if( todo >= nstate ) {
                // Reduction or error
                reduce( todo, error );
            } else {
                // Shift
                fprintf( actout, "\tyysp[0].state = state%d;\n", todo );
                fprintf( actout, "\tbreak;\n" );
            }
        }
    }
    if( switched ) {
        fprintf( actout, "    default: ;\n" );
    }
    todo = action[ parent_token ];
    if( todo != error ) {
        // There is a parent production
        // For now, try parents only when there is no default action
        fprintf( actout, "\treturn( state%d( yysp, token ) );\n", todo );
    } else if( default_action != 0 ) {
        reduce( default_action, error );
    } else {
        fprintf( actout, "\treturn( ERROR );\n" );
    }
    if( switched ) {
        fprintf( actout, "    }\n    return( SHIFT );\n" );
    }
    epilog();
}

static void epilog()
{
    fprintf( actout, "}\n" );
}

static void putambig( int i, int state, int token )
{
    fprintf( actout, "#define\tYYAMBIGS%u\t\t%d\n", i, state );
    fprintf( actout, "#define\tYYAMBIGT%u\t\t%d\n", i, token );
}

static void print_token( int token )
{
    int symnum;

    for( symnum = 0; symnum < nsym; ++ symnum ) {
        if( symtab[symnum]->token == token ) break;
    }
    if( symnum == nsym ) {
        printf( " %d", token );
    } else {
        printf( " %s", symtab[symnum]->name );
    }
}

void genobj( void )
{
    short *token, *action, *base, *other, *parent, *size;
    register short *p, *q, *r, *s;
    short error, tokval, redun, *test, *best;
#if 1
    short *same, *diff;
#endif
    a_sym *sym;
    a_pro *pro;
    a_state *x;
    a_shift_action *tx;
    a_reduce_action *rx;
    int i, j, savings, max, ntoken, dtoken, ptoken;
    unsigned num_default, num_parent;

    num_default = num_parent = 0;
    ntoken = 0;
    for( i = 0; i < nterm; ++i ) {
        if( (j = symtab[i]->token) > ntoken ) {
            ntoken = j;
        }
    }
    dtoken = ++ntoken;
    ptoken = ++ntoken;
    for( i = nterm; i < nsym; ++i ) {
        symtab[i]->token = ++ntoken;
    }
    ++ntoken;

    error = nstate + npro;
    action = CALLOC( ntoken, short );
    for( i = 0; i < ntoken; ++i ) {
        action[i] = error;
    }
    preamble();
    token = CALLOC( ntoken, short );
    test = CALLOC( ntoken, short );
    best = CALLOC( ntoken, short );
    base = CALLOC( nstate, short );
    other = CALLOC( nstate, short );
    parent = CALLOC( nstate, short );
    size = CALLOC( nstate, short );
    for( i = nstate; --i >= 0; ) {
                for( s = action + ntoken; --s >= action; ) {
                    *s = error;
                }
        x = statetab[i];
        q = token;
        for( tx = x->trans; sym = tx->sym; ++tx ) {
            action[*q++ = sym->token] = tx->state->sidx;
        }
        savings = 0;
        for( rx = x->redun; pro = rx->pro; ++rx ) {
            redun = pro->pidx + nstate;
            p = Members( rx->follow, setmembers );
            if( p - setmembers > savings ) {
                savings = p - setmembers;
                r = q;
            }
            if( p - setmembers ) {
                protab[pro->pidx]->used = TRUE;
            }
            while( --p >= setmembers ) {
                tokval = symtab[*p]->token;
                action[*q++ = tokval] = redun;
            }
        }
        if( savings ) {
            tokval = other[i] = action[*r];
            action[*q++ = dtoken] = tokval;
            p = r;
            while( --savings >= 0 )
                action[*p++] = error;
            while( p < q )
                *r++ = *p++;
            q = r;
            ++ num_default;
        } else
            other[i] = error;
        r = q;
        size[i] = r - token;
        max = 0;
        parent[i] = nstate;
        for( j = nstate; --j > i; ) {
            // FOR NOW -- only use parent if no default here or same default
            if( other[i] != error && other[i] != other[j] ) continue;
            savings = 0;
            x = statetab[j];
            q = (p = test) + ntoken;
            for( tx = x->trans; sym = tx->sym; ++tx )
                if( action[sym->token] == tx->state->sidx ) {
                    ++ savings;
                    *p++ = sym->token;
                } else {
                    if( action[ sym->token ] == error ) -- savings;
                    *--q = sym->token;
                }
            for( rx = x->redun; pro = rx->pro; ++rx ) {
                if( (redun = pro->pidx + nstate) == other[j] )
                    redun = error;
                redun = pro->pidx + nstate;
                s = Members( rx->follow, setmembers );
                while( --s >= setmembers ) {
                    tokval = symtab[*s]->token;
                    if( action[tokval] == redun ) {
                        ++ savings;
                        *p++ = tokval;
                    } else {
                        if( action[ tokval ] == error ) -- savings;
                        *--q = tokval;
                    }
                }
            }
            if( other[j] != error ) {
                if( other[j] == other[i] ) {
                    ++ savings;
                    *p++ = dtoken;
                } else {
                    *--q = dtoken;
                }
            }
#if 0
            printf( "state %d calling state %d saves %d:",
                        i, j, savings );
            for( s = test; s < p; ++ s ) {
                print_token( *s );
            }
            printf( " costs" );
            for( s = test + ntoken; --s >= q; ) {
                if( action[ *s ] == error ) {
                    print_token( *s );
                }
            }
            printf( "\n" );
#endif
            if( savings > max ) {
                max = savings;
                same = p;
                diff = q;
                s = test;  test = best;  best = s;
                parent[i] = j;
            }
        }
        if( max < 1 ) { // Could raise threshold for performance
            s = r;
        } else {
            ++ num_parent;
            s = token;
            p = same;
            while( --p >= best )
                action[*p] = error;
            for( q = token; q < r; ++q )
                if( action[*q] != error )
                    *s++ = *q;
            p = best + ntoken;
            while( --p >= diff )
                if( action[*p] == error )
                    *s++ = *p;
            tokval = parent[i];
            action[*s++ = ptoken] = tokval;
        }
        gencode( i, token, s, action, dtoken, ptoken, error );
        while( --s >= token )
            action[*s] = error;
    }
    for( i = 0; i < nambig; ++i ) {
        putambig( i, base[ambiguities[i].state], ambiguities[i].token );
    }
    putnum( "YYNOACTION", error - nstate + dtoken );
    putnum( "YYEOFTOKEN", eofsym->token );
    putnum( "YYERRTOKEN", errsym->token );
    putnum( "YYETOKEN", errsym->token );
    putnum( "YYERR", errstate->sidx );
    fprintf( actout, "#define YYSTART   state%d\n", startstate->sidx );
    fprintf( actout, "#define YYSTOP    state%d\n", eofsym->enter->sidx );
    printf( "%u states, %u with defaults, %u with parents\n",
                nstate, num_default, num_parent );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?