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 + -
显示快捷键?