⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 squash.c

📁 一个c语言写做的编译器的源码
💻 C
字号:
/*@A (C) 1992 Allen I. Holub                                                */
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <tools/debug.h>
#include <tools/set.h>
#include <tools/compiler.h>

#include "dfa.h"
#include "globals.h"

/* SQUASH.C -- This module contains the routines to compress a table
 * horizontally and vertically by removing redundant columns and rows, and then
 * print the compressed table. I haven't been as careful about making this
 * routine general purpose because it's only useful to LeX. The pairs
 * compression routines in pairs.c are used to compress the occs- and
 * llama-generated tables so they're a little more complicated.
 */

PRIVATE int	Col_map[ MAX_CHARS ];
PRIVATE int	Row_map[ DFA_MAX   ];

#define NCOLS	16
#define TYPE	 "YY_TTYPE"  /* Declared type of output tables.		*/
#define SCLASS   "YYPRIVATE" /* Storage class of all the tables		*/

/*----------------------------------------------------------------------
 * Local statics. (Externs are declared in dfa.h.)
 */

PRIVATE int col_equiv	P(( int *col1, int *col2,int nrows	));
PRIVATE void col_cpy	P(( int *dest, int *src, int nrows, \
				          int n_src_cols, int n_dest_cols ));
PRIVATE void reduce		P(( ROW *dtran, int *p_nrows,int *p_ncols ));
PRIVATE void print_col_map	P(( FILE *fp				  ));
PRIVATE void print_row_map	P(( FILE *fp,int nrows			  ));
PRIVATE void pmap		P(( FILE *fp, int *p, int n		  ));
/*----------------------------------------------------------------------*/
#define ROW_EQUIV(r1,r2,ncols)	(memcmp( r1, r2, ncols * sizeof(int))==0 )
#define ROW_CPY(r1,r2,ncols)	(memcpy( r1, r2, ncols * sizeof(int))	 )
/*----------------------------------------------------------------------*/
PUBLIC  int	squash( fp, dtran, nrows, ncols, name )
FILE	*fp;
ROW	*dtran;
int	nrows, ncols;
char	*name;
{
    /* Compress (and output) dtran using equivalent-column elimination.
     * Return the number of bytes required for the compressed tables
     * (including the map but not the accepting array).
     */

    int	oncols = ncols;				  /* original column count */
    int	onrows = nrows;				  /* original row    count */

    reduce( dtran, &nrows, &ncols );		  /* Compress the tables   */

    print_col_map ( fp );
    print_row_map ( fp, onrows );

    fprintf(fp, "%s %s %s[ %d ][ %d ]=\n", SCLASS, TYPE, name, nrows, ncols);
    print_array( fp, (int *)dtran, nrows, ncols );

    return(  ( nrows * ncols  * sizeof(TTYPE))			/* dtran   */
	    +(         onrows * sizeof(TTYPE))			/* row map */
	    +(         oncols * sizeof(TTYPE)) );		/* col map */
}
/*----------------------------------------------------------------------*/
PRIVATE  int col_equiv( col1, col2, nrows )
int	*col1, *col2;
int	nrows;
{
    /* Return 1 if the two columns are equivalent, else return 0 */

    while( --nrows >= 0  &&  *col1 == *col2 )
    {
	col1 += MAX_CHARS;	  /* Advance to next cell in the column */
	col2 += MAX_CHARS;
    }
    return( !(nrows >= 0) );
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
PRIVATE	void col_cpy( dest, src, nrows, n_src_cols, n_dest_cols )
int	*dest;		/* Top of destination column			*/
int	*src;		/* Top of source column				*/
int	nrows;		/* Number of rows				*/
int	n_src_cols;	/* Number of columns in source array		*/
int	n_dest_cols;	/* Number of columns in destination array	*/
{
    /* Copy a column from one array to another. Both arrays are nrows deep,
     * the source array is n_src_cols wide and the destination array is
     * n_dest_cols wide.
     */

    while( --nrows >= 0  )
    {
       *dest   = *src;
	dest  += n_dest_cols;
	src   += n_src_cols;
    }
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
PRIVATE	void	reduce( dtran, p_nrows, p_ncols )
ROW	*dtran;			/* DFA transition table			*/
int	*p_nrows;		/* # of states in dtran			*/
int	*p_ncols;		/* Pointer to column count		*/
{
    /* Reduce dtran horizontally and vertically, filling the two map arrays
     * with the character mapping to the final, reduced transition table.
     * Return the number of columns in the reduced dtran table.
     *
     * Col_map is the x (character) axis, Row_map is the y (next state) axis.
     */

    int  ncols = *p_ncols;   /* number of columns in original machine  	  */
    int  nrows = *p_nrows;   /* number of rows    in original machine  	  */
    int  r_ncols;	     /* number of columns in reduced machine   	  */
    int  r_nrows;	     /* number of rows    in reduced machine   	  */
    SET	 *save;	     	     /* rows or columns that will remain in table */
    int	 *current;	     /* first of several identical columns	  */
    int	 *compressed;	     /* pointer to compressed array	  	  */
    int	 *p;
    int	 i, j;

    /* ............................................................
     *	First do the columns.
     */

    memset( Col_map, -1, sizeof(Col_map) );
    save = newset();

    for( r_ncols = 0 ;; r_ncols++ )
    {
	/* Skip past any states in the Col_map that have already been
	 * processed. If the entire Col_map has been processed, break.
	 */

	for(i = r_ncols;  Col_map[i] != -1  && i < ncols  ; i++ )
	    ;

	if( i >= ncols )
	    break;

	/* Add the current column to the save set. It eventually ends up
	 * in the reduced array as column "r_ncols" so modify the Col_map
	 * entry accordingly. Now, scan trough the array looking for
	 * duplicates of the current column (pointed to by current). If you
	 * find a duplicate, make the associated Col_map entry also point to
	 * "r_ncols."
	 */

	ADD( save, i );
	Col_map[i] = r_ncols;

	current = &dtran[0][i];
	p       = current + 1;

	for( j = i; ++j < ncols ; p++ )
	    if( Col_map[j]==-1 && col_equiv(current, p, nrows) )
		Col_map[j] = r_ncols ;
    }

    /* Compress the array horizontally by removing all of the columns that
     * aren't in the save set. We're doing this by moving all the columns
     * that are in the save set to the proper position in a newly allocated
     * array.  You can't do it in place because there's no guarantee that the
     * equivalent rows are next to each other.
     */

    if( !(compressed = (int *) malloc(nrows * r_ncols * sizeof(int))) )
	ferr("Out of memory");

    p = compressed;
    for( next_member(NULL); (i = next_member(save)) != -1; )
	col_cpy( p++, &dtran[0][i], nrows, ncols, r_ncols );

    /* ............................................................
     *  Eliminate equivalent rows, working on the reduced array
     *  created in the previous step. The algorithm used is the
     *  same.
     */

    memset( Row_map, -1, sizeof(Row_map) );
    CLEAR( save );

    for( r_nrows = 0 ;; r_nrows++ )
    {
	for( i = r_nrows; Row_map[i] != -1  && i < nrows; i++ )
		;

	if( i >= nrows )
		break;

	ADD( save, i );
	Row_map[i] = r_nrows;

	current = compressed + ((i  ) * r_ncols );
	p       = compressed + ((i+1) * r_ncols );

	for( j = i; ++j < nrows ; p += r_ncols )
	    if( Row_map[j]==-1 && ROW_EQUIV(current, p, r_ncols) )
		    Row_map[j] = r_nrows ;
    }

    /*
     * Actually compress rows, copying back into the original array space.
     * Note that both dimensions of the array have been changed.
     */

    p = (int *)dtran;

    for( next_member(NULL); (i = next_member(save)) != -1; )
    {
	ROW_CPY( p, compressed + (i * r_ncols) , r_ncols );
	p += r_ncols;
    }

    delset ( save       );
    free   ( compressed );

    *p_ncols = r_ncols ;
    *p_nrows = r_nrows ;
}
/*----------------------------------------------------------------------*/
PRIVATE	void print_col_map( fp )
FILE	*fp;
{
    static char	*text[] =
    {
       "The Yy_cmap[] and Yy_rmap arrays are used as follows:",
       "",
       " next_state= Yydtran[ Yy_rmap[current_state] ][ Yy_cmap[input_char] ];",
       "",
       "Character positions in the Yy_cmap array are:",
       "",
       "   ^@  ^A  ^B  ^C  ^D  ^E  ^F  ^G  ^H  ^I  ^J  ^K  ^L  ^M  ^N  ^O",
       "   ^P  ^Q  ^R  ^S  ^T  ^U  ^V  ^W  ^X  ^Y  ^Z  ^[  ^\\  ^]  ^^  ^_",
       "        !   \"   #   $   %   &   '   (   )   *   +   ,   -   .   /",
       "    0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?",
       "    @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O",
       "    P   Q   R   S   T   U   V   W   X   Y   Z   [   \\   ]   ^   _",
       "    `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o",
       "    p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~   DEL",
       NULL
    };

    comment(fp, text);
    fprintf(fp, "%s %s  Yy_cmap[%d] =\n{\n     ", SCLASS, TYPE, MAX_CHARS );
    pmap   (fp, Col_map, MAX_CHARS );
}

PRIVATE	void print_row_map( fp, nrows )
FILE	*fp;
int	nrows;
{
    fprintf(fp, "%s %s  Yy_rmap[%d] =\n{\n     ", SCLASS, TYPE, nrows );
    pmap   (fp, Row_map, nrows );
}

PRIVATE void pmap( fp, p, n )
FILE	*fp;					/* output stream    */
int	*p;					/* pointer to array */
int	n;					/* array size	    */
{
    /* Print a one-dimensional array.
    */

    int j;
    for( j = 0; j < (n - 1); j++ )
    {
	fprintf(fp, "%3d," , *p++ );

	if( (j % NCOLS) == NCOLS-1 )
	    fprintf(fp, "\n     ");
    }

    fprintf( fp, "%3d\n};\n\n", *p );
}
/*----------------------------------------------------------------------*/
PUBLIC  void	cnext( fp, name )
FILE	*fp;
char	*name;
{
    /*   Print out a yy_next(state,c) subroutine for the compressed table.
     */

    static char	 *text[] =
    {
	"yy_next(state,c) is given the current state number and input",
	"character and evaluates to the next state.",
	NULL
    };

    comment( fp, text );
    fprintf( fp,
	"#define yy_next(state,c) (%s[ Yy_rmap[state] ][ Yy_cmap[c] ])\n",
	name
    );
}

⌨️ 快捷键说明

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