编译原理上机作业3——算符优先算法

#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;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
算符优先分析算法是一种自底向上的语法分析算法,用于判断输入源程序是否符合语法规则。该算法的主要思想是利用算符优先关系来进行语法分析。 下面是算符优先分析算法的实验步骤: 1. 定义文法:首先需要定义待分析的文法,可以使用巴科斯范式(BNF)或扩展巴科斯范式(EBNF)来示文法。 2. 构造算符优先关系:根据文法中的终结符和运算符,构造算符优先关系。其中,算符优先关系是一个二维矩阵,行和列分别代两个运算符,中的值示它们之间的优先关系。 3. 读入待分析的源程序:从文件中读入待分析的源程序,可以使用词法分析器将源程序转换成一个个单词。 4. 进行算符优先分析:根据算符优先关系和输入的单词序列,利用栈来进行算符优先分析。具体过程如下: - 初始化栈,将结束符号 $ 和文法的开始符号压入栈中。 - 从输入的单词序列中读入一个单词。 - 判断栈顶符号和当前读入的单词之间的优先关系,如果栈顶符号的优先级高于当前单词,则进行规约操作,即将栈顶符号和它的子树弹出,然后根据规约产生式将它们替换成非终结符号。 - 如果栈顶符号和当前单词之间的优先级低于或等于当前单词,则进行移进操作,即将当前单词压入栈中。 - 重复上述步骤,直到栈中只剩下结束符号 $,并且输入的单词序列已经分析完毕。 5. 输出分析结果:如果分析成功,则输出“分析成功”;否则,输出“分析失败”。 以上就是算符优先分析算法的实验步骤,希望对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值