編譯原理上機作業3——算符優先演算法

塵埃092發表於2013-11-09
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char grammer[200][200];
char terSymbol[200];
char nterSymbol[200];
int firstVT[100][100];
int lastVT[100][100];
int vtnum, vnnum, pronum;
int M[200][200];
int local_terminal( char ch )
{
	for( int i = 0; i < vtnum; i++ )
		if( ch == terSymbol[i] )
			return i;
	return -1;
}
int local_nterminal( char ch )
{
	for( int i = 0; i < vnnum; i++ )
		if( ch == nterSymbol[i] )
			return i;
	return -1;
}
bool canbe_empty( char ch )
{
    for( int i = 0; i < pronum; i++ )
    {
         if( grammer[i][0] == ch )
         {
             if( grammer[i][3] == '$' )
                 return true;
         }
    }
    return false;
}
bool have_first( int k )
{
	for( int i = 0; i < vtnum; i++ )
		if( firstVT[k][i] == 1 )
			return true;
	return false;
}
bool have_last( int k )
{
	for( int i = 0; i < vtnum; i++ )
		if( lastVT[k][i] == 1 )
			return true;
	return false;
}
void addfirstvtSet( char ch, char X )
{
	int X_num = local_nterminal(X);
	if( local_terminal(ch) != -1 )
		firstVT[X_num][local_terminal(ch)] = 1;
	else
	{
		int ch_num = local_nterminal(ch);
		for( int i = 0; i < vtnum; i++ )
			if( firstVT[ch_num][i] == 1 )
				firstVT[X_num][i] = 1;
	}
}
void addlastvtSet( char ch, char X )
{
	int X_num = local_nterminal(X);
	if( local_terminal(ch) != -1 )
		lastVT[X_num][local_terminal(ch)] = 1;
	else
	{
		int ch_num = local_nterminal(ch);
		for( int i = 0; i < vtnum; i++ )
			if( lastVT[ch_num][i] == 1 )
				lastVT[X_num][i] = 1;
	}
}
void firstvt( char X )
{
	int p, flag = 1;
	for( int i = 0; i < pronum; i++ )
	{
		if( grammer[i][0] == X )
		{
			p = 3;
			while( grammer[i][p] != '\0' )
			{
				if( local_terminal(grammer[i][p]) != -1 )
				{
					addfirstvtSet( grammer[i][p], X );
					break;
				}
				else
				{
					do
					{
					    if( grammer[i][p] != X )
						{
				            flag = 1;
				            if(!have_first(local_nterminal(grammer[i][p]))) 
				               firstvt( grammer[i][p] );
				            addfirstvtSet( grammer[i][p], X );
				            if( canbe_empty(grammer[i][p]) )
				            {
				                flag = 0;
							       p++;
				            }
				        }
				        else
				            break;
					}while( canbe_empty(grammer[i][p]) && grammer[i][p] != '\0' );
				    if( local_terminal(grammer[i][p+1]) != -1 && grammer[i][p+1] != '\0' && flag )
                        addfirstvtSet( grammer[i][p+1], X );
					break;
				}
            }
		}
	}
}
void lastvt( char X )
{
	int p, flag = 1;
	for( int i = 0; i < pronum; i++ )
	{
		if( grammer[i][0] == X )
		{
			p = strlen(grammer[i])-1;
			while( p !=  2 )
			{
				if( local_terminal(grammer[i][p]) != -1 )
				{
					addlastvtSet( grammer[i][p], X );
					break;
				}
				else
				{
					do
					{
						if( grammer[i][p] != X )
						{
							flag = 1;
							if(!have_last(local_nterminal(grammer[i][p]))) 
								lastvt( grammer[i][p] );
							addlastvtSet( grammer[i][p], X );
							if( canbe_empty(grammer[i][p]) )
							{
								flag = 0;
								p--;
							}
						}
						else
							break;

					}while( canbe_empty(grammer[i][p]) && p != 2 );
 					if( local_terminal(grammer[i][p-1]) != -1 && p != 2 && flag )
                        	addlastvtSet( grammer[i][p-1], X );
					break;

				}
			}
		}
	}
}
void print_table()
{
	char x1 = '>';
	char x2 = '<';
	char x3 = '=';
	printf( "   " );
	for( int i = 0; i < vtnum; i++ )
		printf( "%c ", terSymbol[i] );
	printf( "\n" );
	for( int i = 0; i < vtnum; i++ )
	{
		printf( "%c ", terSymbol[i] );
		for( int j = 0; j < vtnum; j++ )
		{
			if( M[i][j] == 1 )
				printf( "%2c", x1 );
			if( M[i][j] == 2 )
				printf( "%2c", x2 );
			if( M[i][j] == 3 )
				printf( "%2c", x3 );
			if( M[i][j] == -1)
				printf( "  " );
		}
		printf( "\n" );
	}
	printf( "\n\n" );
}
void create_table()
{
	/* > means 1
	 * < means 2
	 * = means 3
	 */
	for( int i = 0; i < vtnum; i++ )
		for( int j = 0; j < vtnum; j++ )
			M[i][j] = -1;
	for( int i = 0; i < vtnum; i++ )
	{
		M[i][vtnum-1] = 1;
		M[vtnum-1][i] = 2;
	}
	M[vtnum-1][vtnum-1] = 3;
	for( int i = 0; i < pronum; i++ )
	{
		int len = strlen(grammer[i]);
		for( int j = 3; j < len-1; j++ )
		{
			int a1 = local_terminal(grammer[i][j]);
			int b1 = local_terminal(grammer[i][j+1]);
			int c1 = local_terminal(grammer[i][j+2]);
			int a2 = local_nterminal(grammer[i][j]);
			int b2 = local_nterminal(grammer[i][j+1]);
			int c2 = local_nterminal(grammer[i][j+2]);
			if( a1 != -1 && b1 != -1 )
			{
				M[a1][b1] = 3;
			//	print_table();
			}
			if( j <= len-2 && a1 != -1 && b1 == -1 && c1 != -1 )
			{
				M[a1][c1] = 3;
			//	print_table();
			}
			if( a1 != -1 && b1 == -1 )
			{
				for( int i = 0; i < vtnum; i++ )
				{
					if( firstVT[b2][i] )
						M[a1][i] = 2;
				}
			//	print_table();
			}
			if( a1 == -1 && b1 != -1 )
			{
				for( int i = 0; i < vtnum; i++ )
				{
					if( lastVT[a2][i] )
						M[i][b1] = 1;
				}
			//	print_table();
			}
		}
	}

}
char prime( char * p )
{
	char temp[100];
	int flag, i, j, begin, end, begin_flag, end_flag;
	begin = -1;
	end = -1;
	i = j = 0;
	while( i < strlen(p) && j < strlen(p)-1 )
	{
		i = j;
		while( local_terminal(*(p+i)) == -1 )
			i++;
		begin = local_terminal(*(p+i));	
		j = i+1;
		while( local_terminal(*(p+j)) == -1 )
			j++;
		end = local_terminal(*(p+j));
		if( M[begin][end] == 2 )
			begin_flag = i+1;
		if( M[begin][end] == 1 )
			end_flag = j-1;
	}
	for( int i = begin_flag, j= 0; i <= end_flag; i++ )
	{
		temp[j++] = *(p+i);
		temp[j] = '\0';
	}
	for( int i = 0; i < pronum; i++ )
	{
		char a[100];
		flag = 0;
		char *p = &grammer[i][3];
		char *s = a;
		while( (*s = *p) != '\0' )
		{
			s++;
			p++;
		}
		if( !strcmp(a,temp) )
			return grammer[i][0];
	}
	return -1;
}
void control()
{
	/* This function had a little bug, but i don't wanna correct it */
	char stack[200], input[100], save[100];
	int top = 0, temp, j, find, flag;
	stack[top++] = '$';
	scanf( "%s", input );
	for( int i = 0; i < strlen(input); i++ )
	{
		flag = 1;
		int a = local_terminal(input[i]);
		if( local_terminal(stack[top-1]) != -1 )  
			find = top-1;
		else
			find = top-2;
		while( !(top ==2 && input[i] == '$') )
		{
			j = local_terminal(stack[find]);
			if( M[j][a] == 1  )		// S[j] > a 
			{
				do
				{
					find--;
					if( local_terminal(stack[find]) == -1 )
						find--;
				}while( M[local_terminal(stack[find])][j] != 2 );  // S[j] < Q
				//  stack[find+1] ---- stack[top-1] guiyue   top = find +1   
				int in = 0;
				for( int t = find; t <= top-1; t++ )
					save[in++] = stack[t];
				save[in] = '$';
				save[in+1] = '\0';
	//			printf( "%s", save );
				top = find+1;
				stack[top++] = prime( save );
	//				printf( "wrong" );
			}
			else
			{
				flag = 0;
				if( M[j][a] == 2 || M[j][a] == 3 )
					stack[top++] = input[i];
				else
					printf( "error" );
				break;
			}
		}
		if( flag )
			printf( "success\n" );
	}
}
int main()
{
	pronum = 0;
	char temp[100];
	freopen( "1.txt", "r", stdin );
	printf( "please input terminal-Symbol\n" );
		scanf( "%s", terSymbol );
	printf( "plaese input no-terminal-Symbol\n" );
		scanf( "%s", nterSymbol );
	vtnum = strlen(terSymbol);
	vnnum = strlen(nterSymbol);
	printf( "please input the grammarElement\n" );
	while( scanf( "%s", temp) && temp[0] != '#' )
		strcpy(grammer[pronum++], temp );
	for( int i = 0; i < 100; i++ )
		for( int j = 0; j < 100; j++ )
		{
			firstVT[i][j] = 0;
			lastVT[i][j] = 0;
		}
	for( int i = 0; i < vnnum; i++ )
		firstvt( nterSymbol[i] );
	//print the firset set
	for( int i = 0; i < vnnum; i++ )
	{
		for( int j = 0; j < vtnum; j++ )
			printf( "%d ", firstVT[i][j] );
		printf( "\n" );
	}

	for( int i = 0; i < vnnum; i++ )
		lastvt( nterSymbol[i] );
	//print the last set
	printf( "\n\n\n" );
	for( int i = 0; i < vnnum; i++ )
	{
		for( int j = 0; j < vtnum; j++ )
			printf( "%d ", lastVT[i][j] );
		printf( "\n" );
	}
	create_table();
	print_table();
	control();
	return 0;
}

相關文章