/*************************************************************** VERBOSE.C This file containts VERBOSE file writer of ZUBR. PART OF : ZUBR - Parsers generator for multiple syntax language compilers . COMPILE : . NOTE : . Copyright (C) 1995 - 2026 by Andrey V.Kosteltsev. All Rights Reserved. ***************************************************************/ /* This file contant RUSSIAN letters( code-page: UTF-8 ) ***************************************************************/ #include #ifndef __NO_COMPILE static int *null_rules; /* NOTE * In this file for output '\t'(tab) symbol use 12 space characters. My be use the following string 'u" ' for find that symbols. * END */ void log_unused( void ) /*************************************************************** Description : log unused Concepts : Use Global Variable: int nrules; | main.c char **symbol_name; | main.c int *ritem; | main.c int *rrhs; | main.c FILE *verbose_file; | main.c int *rules_used; | mkpar.c Use Functions : Parameters : [void] Return : [void] ***************************************************************/ { register int i; register int *p; mpu_fprintf( verbose_file, MPU_UCS2( "\n\nRules never reduced:\n" ) ); for( i = 3; i < nrules; ++i ) { if( !rules_used[i] ) { mpu_fprintf( verbose_file, MPU_UCS2( " %s :" ), symbol_name[rlhs[i]]); for( p = ritem + rrhs[i]; *p >= 0; ++p ) mpu_fprintf( verbose_file, MPU_UCS2( " %s" ), symbol_name[*p] ); mpu_fprintf( verbose_file, MPU_UCS2( " (%d)\n" ), i - 2 ); } } } /******* End of log_unused( void ) *************************/ void log_conflicts( void ) /*************************************************************** Description : log conflicts Concepts : Use Global Variable: FILE *verbose_file; | main.c int nstates; | lr0.c int *SRconflicts; | mkpar.c int *RRconflicts; | mkpar.c Use Functions : Parameters : [void] Return : [void] ***************************************************************/ { register int i; mpu_fprintf( verbose_file, MPU_UCS2( "\n\n" ) ); for( i = 0; i < nstates; i++ ) { if( SRconflicts[i] || RRconflicts[i] ) { mpu_fprintf( verbose_file, MPU_UCS2( "State %d contains " ), i); if( SRconflicts[i] == 1 ) mpu_fprintf( verbose_file, MPU_UCS2( "1 shift/reduce conflict" ) ); else if( SRconflicts[i] > 1 ) mpu_fprintf( verbose_file, MPU_UCS2( "%d shift/reduce conflicts" ), SRconflicts[i] ); if( SRconflicts[i] && RRconflicts[i] ) mpu_fprintf( verbose_file, MPU_UCS2( ", u" ) ); if( RRconflicts[i] == 1 ) mpu_fprintf( verbose_file, MPU_UCS2( "1 reduce/reduce conflict" ) ); else if( RRconflicts[i] > 1 ) mpu_fprintf( verbose_file, MPU_UCS2( "%d reduce/reduce conflicts" ), RRconflicts[i] ); mpu_fprintf( verbose_file, MPU_UCS2( ".\n" ) ); } } /* End of for( i = 0; i < nstates; i++ ) */ } /******* End of log_conflicts( void ) **********************/ void print_conflicts( int state ) /*************************************************************** Description : print conflicts Concepts : Use Global Variable: char **symbol_name; | main.c FILE *verbose_file; | main.c action **parser; | mkpar.c int final_state; | mkpar.c Use Functions : Parameters : int state Return : [void] ***************************************************************/ { register int symbol = 0, act = 0, number = 0; register action *p; symbol = -1; for( p = parser[state]; p; p = p->next ) { if( p->suppressed == 2 ) continue; if( p->symbol != symbol ) { symbol = p->symbol; number = p->number; if( p->action_code == SHIFT ) act = SHIFT; else act = REDUCE; } else if( p->suppressed == 1 ) { if( state == final_state && symbol == 0 ) { mpu_fprintf( verbose_file, MPU_UCS2( "%d: shift/reduce conflict (accept, reduce %d) on $end\n" ), state, p->number - 2 ); } else { if( act == SHIFT ) { mpu_fprintf( verbose_file, MPU_UCS2( "%d: shift/reduce conflict (shift %d, reduce %d) on %s\n" ), state, number, p->number - 2, symbol_name[symbol] ); } else { mpu_fprintf( verbose_file, MPU_UCS2( "%d: reduce/reduce conflict (reduce %d, reduce %d) on %s\n" ), state, number - 2, p->number - 2, symbol_name[symbol] ); } } } /* End if( p->suppressed == 1 ) */ } /* End of for( p = parser[state]; p; p = p->next ) */ } /******* End of print_conflicts( int state ) ***************/ void print_core( int state ) /*************************************************************** Description : print core Concepts : Use Global Variable: char **symbol_name; | main.c int *ritem; | main.c int *rrhs; | main.c int *rlhs; | main.c FILE *verbose_file; | main.c core **state_table; | lalr.c Use Functions : Parameters : int state Return : [void] ***************************************************************/ { register int i; register int k; register int rule; register core *statep; register int *sp; register int *sp1; statep = state_table[state]; k = statep->nitems; for( i = 0; i < k; i++ ) { sp1 = sp = ritem + statep->items[i]; while( *sp >= 0 ) ++sp; rule = -(*sp); mpu_fprintf( verbose_file, MPU_UCS2( " %s : " ), symbol_name[rlhs[rule]] ); for( sp = ritem + rrhs[rule]; sp < sp1; sp++ ) mpu_fprintf( verbose_file, MPU_UCS2( "%s " ), symbol_name[*sp] ); mpu_putc( '.', verbose_file ); while( *sp >= 0 ) { mpu_fprintf( verbose_file, MPU_UCS2( " %s" ), symbol_name[*sp] ); sp++; } mpu_fprintf( verbose_file, MPU_UCS2( " (%d)\n" ), -2 - *sp ); } /* End of for( i = 0; i < k; i++ ) */ } /******* End of print_core( int state ) ********************/ void print_nulls( int state ) /*************************************************************** Description : print nulls Concepts : Use Global Variable: int *rrhs; | main.c int *rlhs; | main.c FILE *verbose_file; | main.c action **parser; | mkpar.c static int *null_rules; | this file Use Functions : Parameters : int state Return : [void] ***************************************************************/ { register action *p; register int i, j, k, nnulls; nnulls = 0; for( p = parser[state]; p; p = p->next ) { if( p->action_code == REDUCE && (p->suppressed == 0 || p->suppressed == 1) ) { i = p->number; if( rrhs[i] + 1 == rrhs[i+1] ) { for( j = 0; j < nnulls && i > null_rules[j]; ++j ) continue; if( j == nnulls ) { ++nnulls; null_rules[j] = i; } else if( i != null_rules[j] ) { ++nnulls; for( k = nnulls - 1; k > j; --k ) null_rules[k] = null_rules[k-1]; null_rules[j] = i; } } /* End if( rrhs[i] + 1 == rrhs[i+1] ) */ } } /* End of for( p = parser[state]; p; p = p->next ) */ for( i = 0; i < nnulls; ++i ) { j = null_rules[i]; mpu_fprintf( verbose_file, MPU_UCS2( " %s : . (%d)\n" ), symbol_name[rlhs[j]], j - 2 ); } mpu_fprintf( verbose_file, MPU_UCS2( "\n" ) ); } /******* End of print_nulls( int state ) *******************/ void print_shifts( action *p ) /*************************************************************** Description : print shifts Concepts : Use Global Variable: char **symbol_name; | main.c FILE *verbose_file; | main.c Use Functions : Parameters : action *p Return : [void] ***************************************************************/ { register int count; register action *q; count = 0; for( q = p; q; q = q->next ) { if( q->suppressed < 2 && q->action_code == SHIFT ) ++count; } if( count > 0 ) { for( ; p; p = p->next ) { if( p->action_code == SHIFT && p->suppressed == 0 ) mpu_fprintf( verbose_file, MPU_UCS2( " %s shift %d\n" ), symbol_name[p->symbol], p->number ); } } } /******* End of print_shifts( action *p ) ******************/ void print_reductions( action *p, int defred ) /*************************************************************** Description : print reductions Concepts : Use Global Variable: char **symbol_name; | main.c FILE *verbose_file; | main.c Use Functions : Parameters : action *p, int defred Return : [void] ***************************************************************/ { register int k, anyreds; register action *q; anyreds = 0; for( q = p; q ; q = q->next ) { if( q->action_code == REDUCE && q->suppressed < 2 ) { anyreds = 1; break; } } if( anyreds == 0 ) mpu_fprintf( verbose_file, MPU_UCS2( " . error\n" ) ); else { for( ; p; p = p->next ) { if( p->action_code == REDUCE && p->number != defred ) { k = p->number - 2; if( p->suppressed == 0 ) mpu_fprintf( verbose_file, MPU_UCS2( " %s reduce %d\n" ), symbol_name[p->symbol], k ); } } if( defred > 0 ) mpu_fprintf( verbose_file, MPU_UCS2( " . reduce %d\n" ), defred - 2 ); } } /******* End of print_reductions( action *p, int defred ) **/ void print_gotos( int stateno ) /*************************************************************** Description : print gotos Concepts : Use Global Variable: char **symbol_name; | main.c FILE *verbose_file; | main.c shifts **shift_table; | lalr.c int *accessing_symbol; | lalr.c Use Functions : Parameters : int stateno Return : [void] ***************************************************************/ { register int i, k; register int as; register int *to_state; register shifts *sp; mpu_putc( '\n', verbose_file ); sp = shift_table[stateno]; to_state = sp->shift; for( i = 0; i < sp->nshifts; ++i ) { k = to_state[i]; as = accessing_symbol[k]; if( ISVAR(as) ) mpu_fprintf( verbose_file, MPU_UCS2( " %s goto %d\n" ), symbol_name[as], k ); } } /******* End of print_gotos( int stateno ) *****************/ void print_actions( int stateno ) /*************************************************************** Description : print actions Concepts : Use Global Variable: FILE *verbose_file; | main.c shifts **shift_table; | lalr.c int *accessing_symbol; | lalr.c action **parser; | mkpar.c int *defred; | mkpar.c int final_state; | mkpar.c Use Functions : void print_shifts (action *p); | this file void print_reductions (action *, int); | --/-- void print_gotos (int stateno); | this file Parameters : int stateno Return : [void] ***************************************************************/ { register action *p; register shifts *sp; register int as; if( stateno == final_state ) mpu_fprintf( verbose_file, MPU_UCS2( " $end accept\n" ) ); p = parser[stateno]; if( p ) { print_shifts( p ); print_reductions( p, defred[stateno] ); } sp = shift_table[stateno]; if( sp && sp->nshifts > 0 ) { as = accessing_symbol[sp->shift[sp->nshifts - 1]]; if( ISVAR(as) ) print_gotos( stateno ); } } /******* End of print_actions( int stateno ) ***************/ void print_state( int state ) /*************************************************************** Description : print state Concepts : Use Global Variable: FILE *verbose_file; | main.c int *SRconflicts; | mkpar.c int *RRconflicts; | mkpar.c Use Functions : void print_conflicts (int state); | this file void print_core (int state); | this file void print_nulls (int state); | this file void print_actions (int stateno); | this file Parameters : int state Return : [void] ***************************************************************/ { if( state ) mpu_fprintf( verbose_file, MPU_UCS2( "\n\n" ) ); if( SRconflicts[state] || RRconflicts[state] ) print_conflicts( state ); mpu_fprintf( verbose_file, MPU_UCS2( "state %d\n" ), state ); print_core( state ); print_nulls( state ); print_actions( state ); } /******* End of print_state( int state ) *******************/ void verbose( void ) /*************************************************************** Description : verbose Concepts : Use Global Variable: int ntokens | main.c int nrules; | main.c int nvars; | main.c char vflag; | main.c FILE *verbose_file; | main.c int nstates; | lr0.c int nunused; | mkpar.c int SRtotal; | mkpar.c int RRtotal; | mkpar.c static int *null_rules; | this file Use Functions : void no_space (void); | error.c void log_unused (void); | this file void log_conflicts (void); | this file void print_state (int state); | this file Parameters : [void] Return : [void] ***************************************************************/ { register int i; if( !vflag ) return; null_rules = (int *)MALLOC( nrules*sizeof(int) ); if( null_rules == 0 ) no_space(); mpu_fprintf( verbose_file, MPU_UCS2( "\n\n" ) ); for( i = 0; i < nstates; i++ ) print_state( i ); FREE( null_rules ); if( nunused ) log_unused(); if( SRtotal || RRtotal ) log_conflicts(); mpu_fprintf( verbose_file, MPU_UCS2( "\n\n%d terminals, %d nonterminals\n" ), ntokens, nvars ); mpu_fprintf( verbose_file, MPU_UCS2( "%d grammar rules, %d states\n" ), nrules - 2, nstates ); mpu_fprintf( verbose_file, MPU_UCS2( "\n\ /************************ End of File **************************/\n" ) ); } /******* End of verbose( void ) ****************************/ #endif /* __NO_COMPILE */ /******************* END OF FILE VERBOSE.C *******************/