編譯原理上機作業2——LL(1)語法分析

塵埃092發表於2013-11-03
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>

char grammer[200][200];
char terSymbol[200];
char nterSymbol[200];
int firstSET[100][100];
int followSET[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 )
{
	if( local_terminal(ch) != -1 )
		return false;
	else
	{
		if(firstSET[local_nterminal(ch)][vtnum-1] == 1)
			return true;
		else
			return false;
	}
}
bool have_first( int k )
{
	for( int i = 0; i < vtnum; i++ )
		if( firstSET[k][i] == 1 )
			return true;
	return false;
}
void addfirstSet( char ch, char X )
{
	int X_num = local_nterminal(X);
	if( local_terminal(ch) != -1 )
		firstSET[X_num][local_terminal(ch)] = 1;
	else
	{
		int ch_num = local_nterminal(ch);
		for( int i = 0; i < vtnum; i++ )
			if( firstSET[ch_num][i] == 1 )
				firstSET[X_num][i] = 1;
	}
}
void first( char X )
{
	int p;
	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 )
				{
					addfirstSet( grammer[i][p], X );
					break;
				}
				else
				{
					if(!have_first(local_nterminal(grammer[i][p]))) 
						first( grammer[i][p] );
					addfirstSet( grammer[i][p], X );
					if( canbe_empty(grammer[i][p]) )
						p++;
					else
						break;
				}
			}
		}
	}
}
bool have_follow( char ch )
{
	int j = local_nterminal(ch);
	for( int i = 0; i < vtnum; i++ )
		if( followSET[j][i] == 1 )
			return true;
	return false;
}
void addfollowSet( char ch, char X, int kind )
{
	int j, k;
	int X_num = local_nterminal(X); 
	if( kind == 1 )		//  add firstSET
	{
		if( (j = local_terminal(ch)) != -1 )	
			followSET[X_num][j] = 1;
		else
		{
			k = local_nterminal(ch);
			for( int i = 0; i < vtnum; i++ )
				if( firstSET[k][i] == 1 )
					followSET[X_num][i] = 1;
		}
	}
	else if( kind == 0 )				// add followSET 
	{
		j = local_nterminal(ch);
		for( int i = 0; i <= vtnum; i++ )
			if( followSET[j][i] == 1 )
				followSET[X_num][i] = 1;
	}
	else
		printf( "wrong" );

}
void follow( char X )
{
	int p;
	// add # to S 
	followSET[0][vtnum-1] = 1;
	for( int i = 0; i < pronum; i++ )
	{
		p = 3;
		while( grammer[i][p] !='\0' && grammer[i][p] != X )
			p++;
		if( grammer[i][p] == X )
		{
			p++;
			if( grammer[i][p] == '\0' )
			{
				if( !have_follow(grammer[i][0]) )
					follow( grammer[i][0] );
				addfollowSet( grammer[i][0], X, 0);
			}
			else
			{
				while(canbe_empty(grammer[i][p]) && grammer[i][p]!='\0')
				{
					addfollowSet( grammer[i][p], X, 1 );//add first set but first can_empty
				    if(!have_follow(grammer[i][0])&&grammer[i][0]!=X)
						follow( grammer[i][0] );
					addfollowSet( grammer[i][0], X, 0 );  //add follow set
					p++;
				}
				if( !canbe_empty(grammer[i][p]) )//first no-empty
					addfollowSet( grammer[i][p], X, 1 );   // add first set
			}
		}
	}
}
void create_table()
{
	for( int i = 0; i < vnnum; i++ )
		for( int j = 0; j < vtnum; j++ )
			M[i][j] = -1;
	for( int i = 0; i < pronum; i++ )
	{
		int S = local_nterminal( grammer[i][0] );
		int t = local_terminal( grammer[i][3] );
		if( grammer[i][3] != '$' )
		{
			for( int j = 0; j < vtnum; j++ )
			{
				if( t != -1 )
				{
					if(M[S][j] == -1 && grammer[i][3] == terSymbol[j])
						M[S][j] = i;
				}
				else
				{
					int B = local_nterminal(grammer[i][3]);
					if( M[S][j] == -1 && firstSET[B][j] == 1)
						M[S][j] = i;
				}
			}
		}
		if( canbe_empty(grammer[i][0]) )
		{
			for( int t = 0; t < vtnum; t++ )
				if( followSET[S][t] == 1 )
					M[S][t] = i;
		}
	}
	for( int i = 0; i < vnnum; i++ )
	{
		for( int j = 0; j < vtnum; j++ )
		{
			if(  M[i][j] == -1  )
				printf( "     ");
			else
				printf( " %s", grammer[M[i][j]] );
		}
		printf( "\n" );
	}
}
int is_terminal( char X )
{
	for( int i = 0; i < vtnum; i++ )
	{
		if( X == terSymbol[i] )
			return 1;
	}
	return 0;
}
int control()
{
	char stack[1000];
	int top = 0;
	char input[200];
	printf( "input the secentences:\n" );
	scanf( "%s", input );
	stack[top++] = '$';
	stack[top++] = grammer[0][0];
	char *p = input;
	while( 1 )
	{
		char X = stack[top-1];  top--;
		if( is_terminal(X) && X != '$' )
		{
			if( X == *p )
			{
				p++;continue;
			}
			else
			{
				printf( "wrong 1\n" );
				return 0;
			}
					
		}
		else
		{
			if( X == '$' )
			{
				if( X == *p )
				{
					printf( "end\n" );
					return 1;
				}
				else
				{
					printf( "wrong!\n" );
					return 0;
				}
			}
			else
			{
				int t;
				if( (t=M[local_nterminal(X)][local_terminal(*p)]) == -1 )
				{
					printf( "wrong 3!\n" );
					return 0;
				}
				else
				{
					if ( grammer[t][3] == '$' )
						continue;
					else
					{
						for( int i = strlen(grammer[t])-1; i > 2; i-- )
							stack[top++] = grammer[t][i];
					}
				}
			}
		}
	}
};

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++ )
		{
			firstSET[i][j] = 0;
			followSET[i][j] = 0;
		}
	for( int i = 0; i < vnnum; i++ )
		first( nterSymbol[i] );

	//print the firset set
	for( int i = 0; i < vnnum; i++ )
	{
		for( int j = 0; j < vtnum; j++ )
			printf( "%d ", firstSET[i][j] );
		printf( "\n" );
	}

	for( int i = 0; i < vnnum; i++ )
		follow( nterSymbol[i] );
	//print the follow set
	printf( "\n\n\n" );
	for( int i = 0; i < vnnum; i++ )
	{
		for( int j = 0; j < vtnum; j++ )
			printf( "%d ", followSET[i][j] );
		printf( "\n" );
	}
	create_table();
	if( control() )
		printf( "success, this wenfa is true!!!\n\n" );
	else
		printf( "this wenfa is false!!\n\n" );
	return 0;
}
輸入檔案
a^(),$
STB
S->a
S->^
S->(T)
T->SB
B->,SB
B->$
#
(a,a)$

相關文章