📄 yystate.c
字号:
error(FATAL, "Internal [stritem], buffer overflow\n" );
*bp = '\0' ;
return buf;
}
/*----------------------------------------------------------------------*/
PRIVATE void pstate( state )
STATE *state;
{
/* Print one row of the parse table in human-readable form yyout.doc
* (stderr if -V is specified).
*/
int i;
ITEM **item;
ACT *p;
document( "State %d:\n", state->num );
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Print the kernel and epsilon items for the current state. */
for( i=state->nkitems, item=state->kernel_items ; --i >= 0 ; ++item )
document(" %s\n", stritem(*item, (*item)->right_of_dot==0 ));
for( i=state->neitems, item=state->epsilon_items ; --i >= 0 ; ++item )
document( " %s\n", stritem(*item, 1) );
document( "\n" );
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Print out the next-state transitions, first the actions, */
/* then the gotos. */
for( i = 0; i < (MINTERM+USED_TERMS); ++i )
{
if( p = p_action( state->num, i ) )
{
if( p->do_this == 0 )
{
if( p->sym == _EOI_ )
document( " Accept on end of input\n" );
else
error( FATAL, "INTERNAL: state %d, Illegal accept",
state->num);
}
else if( p->do_this < 0 )
document( " Reduce by %d on %s\n", -(p->do_this),
Terms[p->sym]->name );
else
document( " Shift to %d on %s\n", p->do_this,
Terms[p->sym]->name );
}
}
for( i = MINNONTERM; i < MINNONTERM + USED_NONTERMS; i++ )
if( p = p_goto(state->num, i) )
document( " Goto %d on %s\n", p->do_this,
Terms[i]->name );
document("\n");
}
/*----------------------------------------------------------------------*/
PRIVATE void pstate_stdout( state )
STATE *state;
{
document_to( stdout );
pstate( state );
document_to( NULL );
}
/*----------------------------------------------------------------------*/
PRIVATE void pclosure( kernel, closure_items, nitems )
STATE *kernel;
ITEM **closure_items;
int nitems;
{
printf( "\n%d items in Closure of ", nitems );
pstate_stdout( kernel );
if( nitems > 0 )
{
printf( " -----closure items:----\n" );
while( --nitems >= 0 )
printf( " %s\n", stritem( *closure_items++, 0) );
}
}
PRIVATE void make_yy_lhs( prodtab )
PRODUCTION **prodtab;
{
static char *text[] =
{
"The Yy_lhs array is used for reductions. It is indexed by production",
"number and holds the associated left-hand side adjusted so that the",
"number can be used as an index into Yy_goto.",
NULL
};
PRODUCTION *prod;
int i;
comment ( Output, text );
output ( "YYPRIVATE int Yy_lhs[%d] =\n{\n", Num_productions );
for( i = 0; i < Num_productions; ++i )
{
prod = *prodtab++;
output("\t/* %3d */\t%d", prod->num, ADJ_VAL( prod->lhs->val ) );
if( i != Num_productions-1 )
output(",");
if( i % 3 == 2 || i == Num_productions-1 ) /* use three columns */
output( "\n" );
}
output("};\n");
}
/*----------------------------------------------------------------------*/
PRIVATE void make_yy_reduce( prodtab )
PRODUCTION **prodtab;
{
static char *text[] =
{
"The Yy_reduce[] array is indexed by production number and holds",
"the number of symbols on the right-hand side of the production",
NULL
};
PRODUCTION *prod;
int i;
comment ( Output, text );
output ( "YYPRIVATE int Yy_reduce[%d] =\n{\n", Num_productions );
for( i = 0; i < Num_productions; ++i )
{
prod = *prodtab++;
output( "\t/* %3d */\t%d", prod->num, prod->rhs_len );
if( i != Num_productions-1 )
output(",");
if( i % 3 == 2 || i == Num_productions-1 ) /* use three columns */
output( "\n" );
}
output("};\n");
}
/*----------------------------------------------------------------------*/
PRIVATE void make_yy_slhs( prodtab )
PRODUCTION **prodtab;
{
static char *text[] =
{
"Yy_slhs[] is a debugging version of Yy_lhs[]. It is indexed by",
"production number and evaluates to a string representing the",
"left-hand side of the production.",
NULL
};
PRODUCTION *prod;
int i;
comment ( Output, text );
output ( "YYPRIVATE char *Yy_slhs[%d] =\n{\n", Num_productions );
for( i = Num_productions; --i >= 0 ; )
{
prod = *prodtab++;
output("\t/* %3d */\t\"%s\"", prod->num, prod->lhs->name );
output( i != 0 ? ",\n" : "\n" );
}
output("};\n");
}
PRIVATE void make_yy_srhs( prodtab )
PRODUCTION **prodtab;
{
static char *text[] =
{
"Yy_srhs[] is also used for debugging. It is indexed by production",
"number and evaluates to a string representing the right-hand side of",
"the production.",
NULL
};
PRODUCTION *prod;
int i, j;
comment ( Output, text );
output ( "YYPRIVATE char *Yy_srhs[%d] =\n{\n", Num_productions );
for( i = Num_productions; --i >= 0 ; )
{
prod = *prodtab++;
output("\t/* %3d */\t\"", prod->num );
for( j = 0; j < prod->rhs_len ; ++j )
{
output( "%s", prod->rhs[j]->name );
if( j != prod->rhs_len - 1 )
outc( ' ' );
}
output( i != 0 ? "\",\n" : "\"\n" );
}
output("};\n");
}
/*----------------------------------------------------------------------
* The following routines generate compressed parse tables. There's currently
* no way to do uncompressed tables. The default transition is the error
* transition.
*/
PRIVATE void print_reductions()
{
/* Output the various tables needed to do reductions */
PRODUCTION **prodtab;
if(!(prodtab= (PRODUCTION**) malloc(sizeof(PRODUCTION*) * Num_productions)))
error(FATAL,"Not enough memory to output LALR(1) reduction tables\n");
else
ptab( Symtab, (ptab_t)mkprod, prodtab, 0 );
make_yy_lhs ( prodtab );
make_yy_reduce ( prodtab );
output("#ifdef YYDEBUG\n");
make_yy_slhs ( prodtab );
make_yy_srhs ( prodtab );
output("#endif\n");
free( prodtab );
}
/*----------------------------------------------------------------------*/
PRIVATE void mkprod( sym, prodtab )
SYMBOL *sym;
PRODUCTION **prodtab;
{
PRODUCTION *p;
if( ISNONTERM(sym) )
for( p = sym->productions ; p ; p = p->next )
{
#ifdef INTERNAL
if( p->num >= Num_productions )
error( FATAL,"Internal [mkprod], bad prod. num.\n" );
#endif
prodtab[ p->num ] = p ;
}
}
/*----------------------------------------------------------------------*/
PRIVATE void print_tab( table, row_name, col_name, make_private )
ACT **table;
char *row_name; /* Name to use for the row arrays */
char *col_name; /* Name to use for the row-pointers array */
int make_private; /* Make index table private (rows always private) */
{
/* Output the action or goto table. */
int i, j;
ACT *ele, **elep; /* table element and pointer to same */
ACT *e, **p;
int count; /* # of transitions from this state, always >0 */
int column;
SET *redundant = newset(); /* Mark redundant rows */
static char *act_text[] =
{
"The Yy_action table is action part of the LALR(1) transition",
"matrix. It's compressed and can be accessed using the yy_next()",
"subroutine, declared below.",
"",
" Yya000[]={ 3, 5,3 , 2,2 , 1,1 };",
" state number---+ | | |",
" number of pairs in list-+ | |",
" input symbol (terminal)------+ |",
" action-------------------------+",
"",
" action = yy_next( Yy_action, cur_state, lookahead_symbol );",
"",
" action < 0 -- Reduce by production n, n == -action.",
" action == 0 -- Accept. (ie. Reduce by production 0.)",
" action > 0 -- Shift to state n, n == action.",
" action == YYF -- error.",
NULL
};
static char *goto_text[] =
{
"The Yy_goto table is goto part of the LALR(1) transition matrix",
"",
" nonterminal = Yy_lhs[ production number by which we just reduced ]",
"",
" Yyg000[]={ 3, 5,3 , 2,2 , 1,1 };",
" uncovered state-+ | | |",
" number of pairs in list--+ | |",
" nonterminal-------------------+ |",
" goto this state-----------------+",
"",
"It's compressed and can be accessed using the yy_next() subroutine,",
"declared below, like this:",
"",
" goto_state = yy_next( Yy_goto, cur_state, nonterminal );",
NULL
};
comment( Output, table == Actions ? act_text : goto_text );
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Modify the matrix so that, if a duplicate rows exists, only one
* copy of it is kept around. The extra rows are marked as such by setting
* a bit in the "redundant" set. (The memory used for the chains is just
* discarded.) The redundant table element is made to point at the row
* that it duplicates.
*/
for( elep = table, i = 0; i < Nstates ; ++elep, ++i )
{
if( MEMBER( redundant,i ) )
continue;
for( p=elep+1, j=i ; ++j < Nstates ; ++p )
{
if( MEMBER( redundant, j) )
continue;
ele = *elep; /* pointer to template chain */
e = *p; /* chain to compare against template */
if( !e || !ele ) /* either or both strings have no elements */
continue;
for( ; ele && e ; ele=ele->next, e=e->next )
if( (ele->do_this != e->do_this) || (ele->sym != e->sym) )
break;
if( !e && !ele )
{
/* Then the chains are the same. Mark the chain being compared
* as redundant, and modify table[j] to hold a pointer to the
* template pointer.
*/
ADD( redundant, j );
table[j] = (ACT *) elep;
}
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Output the row arrays
*/
for( elep = table, i = 0 ; i < Nstates ; ++elep, ++i )
{
if( !*elep || MEMBER(redundant, i) )
continue;
/* Count the number of transitions from this state */
count = 0;
for( ele = *elep ; ele ; ele = ele->next )
++count;
output("YYPRIVATE YY_TTYPE %s%03d[]={%2d,", row_name,
(int)(elep-table), count);
/*}*/
column = 0;
for( ele = *elep ; ele ; ele = ele->next )
{
++Npairs;
output( "%3d,%-4d", ele->sym, ele->do_this );
if( ++column != count )
outc( ',' );
if( column % 5 == 0 )
output("\n\t\t\t ");
}
/* { */
output( "};\n" );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Output the index array
*/
if( make_private )
output( "\nYYPRIVATE YY_TTYPE *%s[%d] =\n", col_name, Nstates );
else
output( "\nYY_TTYPE *%s[%d] =\n", col_name, Nstates );
output( "{\n/* 0 */ " ); /* } */
for( elep = table, i = 0 ; i < Nstates ; ++i, ++elep )
{
if( MEMBER(redundant, i) )
output( "%s%03d", row_name, (int)((ACT **)(*elep) - table) );
else
output( *elep ? "%s%03d" : " NULL" , row_name, i );
if( i != Nstates-1 )
output( ", " );
if( i==0 || (i % 8)==0 )
output("\n/* %3d */ ", i+1 );
}
/* { */
delset( redundant ); /* Mark redundant rows */
output( "\n};\n");
}
#ifdef DEBUG
#ifdef __TURBOC__
#pragma warn -use
#endif
PRIVATE char *strprod( prod )
PRODUCTION *prod;
{
/* Return a pointer to a string that holds a representation
* of a production.
*/
static char buf[ MAXOBUF ];
char *bp;
int i;
bp = buf;
bp += sprintf( bp, "%s->", prod->lhs->name );
if( prod->rhs_len <= 0 )
bp += sprintf( bp, "<epsilon>" );
else
for( i = 0; i < prod->rhs_len ; ++i )
bp += sprintf(bp, "%s ", prod->rhs[i]->name );
if( bp - buf >= MAXOBUF )
error(FATAL, "Internal [strprod], buffer overflow\n" );
*bp = '\0' ;
return buf;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -