算符优先分析法设计与实现——程序设计与编译原理

1.定义目标语言的语法规则;

    例如:E->E+T|T

               T->T*F|F

               F->(E)|i

2.求解预测分析方法需要的符号集和分析表;

   终结符集合为:{+,*,(,i,)}

   非终结符集为:{E,T,F}

   算符优先分析表为

  + * i ( ) #
+ > < < < > >
* > > < < > >
i > >     > >
( < < < < =  
) > >     > >
# < < < <   =

流程图 、程序    注意函数思想流程图:

#include <iostream>
#include "stdio.h"
#include "stdlib.h"
#include <string>
using namespace std;
char Data[20][20];                    //算符优先关系
char s[100];                          //模拟符号栈s 
char lable[20];                       //文法终极符集
char input[100];                      //文法输入符号串
char In_str[20][10];                  //用于输入串的分析
int k;
char a;
int j;
char q;
int r;                                //文法规则个数
int r1;                               //转化后文法规则个数
char st[10][30];                      //用来存储文法规则
char first[10][10];                   //文法非终结符FIRSTVT集
char last[10][10];                    //文法非终结符LASTVT集
int fflag[10] = { 0 };                //标志第i个非终结符的FIRSTVT集是否已求出
int lflag[10] = { 0 };                //标志第i个非终结符的LASTVT集是否已求出
int deal();                          //对输入串的分析
int Terminator(char c);                //判断字符c是否是终极符
int getIndex(char c);                 //求字符c在算符优先关系表中的下标
void out(int j, int k, char *s);       //打印s栈
void firstvt(char c);                //求非终结符c的FIRSTVT集
void lastvt(char c);                 //求非终结符c的LASTVT集
void table();                        //创建文法优先关系表
int main()
{
	int i, j, k = 0;
	printf("请输入文法规则数:");
	cin >> r;
	printf("请输入文法规则:\n");
	for (i = 0; i<r; i++)
	{
		cin >> st[i];		        //存储文法规则,初始化FIRSTVT集和LASTVT集*/					   
		first[i][0] = 0;            /*first[i][0]和last[i][0]分别表示st[i][0]非终极
									符的FIRSTVT集和LASTVT集中元素的个数*/
		last[i][0] = 0;
	}
	for (i = 0; i<r; i++)          //判断文法是否合法
	{
		for (j = 0; st[i][j] != '\0'; j++)
		{
			if (st[i][0]<'A' || st[i][0]>'Z')
			{
				printf("不是算符文法!\n");
				exit(-1);
			}
			if (st[i][j] >= 'A'&&st[i][j] <= 'Z')
			{
				if (st[i][j + 1] >= 'A'&&st[i][j + 1] <= 'Z')//两非终结符不能相邻
				{
					printf("不是算符文法!\n");
					exit(-1);
				}
			}
		}
	}
	for (i = 0; i<r; i++)
	{
		for (j = 0; st[i][j] != '\0'; j++)
		{
			if ((st[i][j]<'A' || st[i][j]>'Z') && st[i][j] != '-'&&st[i][j] != '>'&&st[i][j] != '|')
				lable[k++] = st[i][j];
		}
	}
	lable[k] = '#';//把井号终结符加入到终结符集合里面
	lable[k + 1] = '\0';
	table();
 
	printf("每个非终结符的FIRSTVT集为:\n");    //输出每个非终结符的FIRSTVT集
	for (i = 0; i<r; i++)
	{
		printf("%c: ", st[i][0]);
		for (j = 0; j<first[i][0]; j++)
		{
			printf("%c ", first[i][j + 1]);
		}
		printf("\n");
	}
	printf("每个非终结符的LASTVT集为:\n");    //输出每个非终结符的LASTVT集
	for (i = 0; i<r; i++)
	{
		printf("%c: ", st[i][0]);
		for (j = 0; j<last[i][0]; j++)
		{
			printf("%c ", last[i][j + 1]);
		}
		printf("\n");
	}
	printf("算符优先分析表如下:\n");
	for (i = 0; lable[i] != '\0'; i++)
		printf("\t%c", lable[i]);
	printf("\n");
	for (i = 0; i<k + 1; i++)
	{
		printf("%c\t", lable[i]);
		for (j = 0; j<k + 1; j++)
		{
			printf("%c\t", Data[i][j]);
		}
		printf("\n");
	}
	printf("请输入文法输入符号串以#结束:");
	while (cin >> input && input != "exit") {
		deal();
		printf("请输入文法输入符号串以#结束:");
	}
 
	system("pause");
}
void table()
{
	char text[20][10];
	int i, j, k, t, l, x = 0, y = 0;
	int m, n;
	x = 0;
	//求firstvt集和lastvt集
	for (i = 0; i<r; i++)
	{
		firstvt(st[i][0]);
		lastvt(st[i][0]);
	}
	//转化文法,化为单候选式文法
	for (i = 0; i<r; i++)
	{
		text[x][y] = st[i][0];
		y++;
		for (j = 1; st[i][j] != '\0'; j++)
		{
			if (st[i][j] == '|')
			{
				text[x][y] = '\0';
				x++;
				y = 0;
				text[x][y] = st[i][0];
				y++;
				text[x][y++] = '-';
				text[x][y++] = '>';
			}
			else
			{
				text[x][y] = st[i][j];
				y++;
			}
		}
		text[x][y] = '\0';
		x++;
		y = 0;
	}
	r1 = x;//更改转换后文法的数目
	printf("转化后的文法为:\n");
	for (i = 0; i<x; i++)                                  //输出转化后的文法规则串
	{
		printf("%s\n", text[i]);
	}
	/*求每个终结符的推导结果(去掉"->"
	后的转化文法,用于最后的规约)*/
	for (i = 0; i<x; i++)
	{
		In_str[i][0] = text[i][0];
		for (j = 3, l = 1; text[i][j] != '\0'; j++, l++)
			In_str[i][l] = text[i][j];
		In_str[i][l] = '\0';
	}
 
	//利用书上算法构造算符优先分析表
	//firstvt[0][0]第一位为firstvt集元素数目
	//lastvt集也一样
	for (i = 0; i<x; i++)
	{
		for (j = 1; text[i][j + 1] != '\0'; j++)
		{
			if (Terminator(text[i][j]) && Terminator(text[i][j + 1]))
			{
				m = getIndex(text[i][j]);
				n = getIndex(text[i][j + 1]);
				Data[m][n] = '=';
			}
			if (text[i][j + 2] != '\0'&&Terminator(text[i][j]) && Terminator(text[i][j + 2]) && !Terminator(text[i][j + 1]))
			{
				m = getIndex(text[i][j]);
				n = getIndex(text[i][j + 2]);
				Data[m][n] = '=';
			}
			if (Terminator(text[i][j]) && !Terminator(text[i][j + 1]))
			{
				for (k = 0; k<r; k++)
				{
					if (st[k][0] == text[i][j + 1])
						break;
				}
				m = getIndex(text[i][j]);
				for (t = 0; t<first[k][0]; t++)
				{
					n = getIndex(first[k][t + 1]);
					Data[m][n] = '<';
				}
			}
			if (!Terminator(text[i][j]) && Terminator(text[i][j + 1]))
			{
				for (k = 0; k<r; k++)
				{
					if (st[k][0] == text[i][j])
						break;
				}
				n = getIndex(text[i][j + 1]);
				for (t = 0; t<last[k][0]; t++)
				{
					m = getIndex(last[k][t + 1]);
					Data[m][n] = '>';
				}
			}
		}
	}
	//将#E#开始文法也加上去求出其对应的firstvt和lastvt集。
	m = getIndex('#');
	for (t = 0; t<first[0][0]; t++)
	{
		n = getIndex(first[0][t + 1]);
		Data[m][n] = '<';
	}
	n = getIndex('#');
	for (t = 0; t<last[0][0]; t++)
	{
		m = getIndex(last[0][t + 1]);
		Data[m][n] = '>';
	}
	Data[n][n] = '=';
}
 
void firstvt(char c)                                       //求FIRSTVT集
{
	int i, j, k, m, n;
	for (i = 0; i<r; i++)
	{
		if (st[i][0] == c)
			break;
	}
	if (fflag[i] == 0)
	{
		n = first[i][0] + 1;
		m = 0;
		do
		{
			if (m == 2 || st[i][m] == '|')
			{
				if (Terminator(st[i][m + 1]))
				{
					first[i][n] = st[i][m + 1];
					n++;
				}
				else
				{
					if (Terminator(st[i][m + 2]))
					{
						first[i][n] = st[i][m + 2];
						n++;
					}
					if (st[i][m + 1] != c)
					{
						firstvt(st[i][m + 1]);
						for (j = 0; j<r; j++)
						{
							if (st[j][0] == st[i][m + 1])
								break;
						}
						for (k = 0; k<first[j][0]; k++)
						{
							int t;
							for (t = 0; t<n; t++)
							{
								if (first[i][t] == first[j][k + 1])
									break;
							}
							if (t == n)
							{
								first[i][n] = first[j][k + 1];
								n++;
							}
						}
					}
				}
			}
			m++;
		} while (st[i][m] != '\0');
		first[i][n] = '\0';
		first[i][0] = --n;//第一位值存firstvt集中元素的个数(字符形式)
		fflag[i] = 1;//表明该非终极符的firstvt集求出来了
	}
}
 
void lastvt(char c)                                        //求LASTVT集
{
	int i, j, k, m, n;
	for (i = 0; i<r; i++)
	{
		if (st[i][0] == c)
			break;
	}
	if (lflag[i] == 0)
	{
		n = last[i][0] + 1;
		m = 0;
		do
		{
			if (st[i][m + 1] == '\0' || st[i][m + 1] == '|')
			{
				if (Terminator(st[i][m]))
				{
					last[i][n] = st[i][m];
					n++;
				}
				else
				{
					if (Terminator(st[i][m - 1]))
					{
						last[i][n] = st[i][m - 1];
						n++;
					}
					if (st[i][m] != c)
					{
						lastvt(st[i][m]);
						for (j = 0; j<r; j++)
						{
							if (st[j][0] == st[i][m])
								break;
						}
						for (k = 0; k<last[j][0]; k++)
						{
							int t;
							for (t = 0; t<n; t++)
							{
								if (last[i][t] == last[j][k + 1])
									break;
							}
							if (t == n)
							{
								last[i][n] = last[j][k + 1];
								n++;
							}
						}
					}
				}
			}
			m++;
		} while (st[i][m] != '\0');
		last[i][n] = '\0';
		last[i][0] = --n;
		lflag[i] = 1;
	}
}
 
int deal()
{
	int i, j;
	int x, y;
	int z;                                 //输入串的长度
	k = 1;
	s[k] = '#';                            //栈置初值
	for (i = 0; input[i] != '\0'; i++);    //计算输入串的长度
	z = i--;
	i = 0;
	while ((a = input[i]) != '\0')
	{
		//j指向最接近栈顶的终极符
		if (Terminator(s[k]))
			j = k;
		else
			j = k - 1;
		x = getIndex(s[j]);//获取最接近栈顶的终极符在终极符表中位置
		y = getIndex(a);//获取第一个输入符号在终极符表中位置
		if (Data[x][y] == '>')//归约
		{
			out(1, k, s);
			printf("%c", a);
			out(i + 1, z, input);
			printf("规约\n");
			do
			{
				q = s[j];
				if (Terminator(s[j - 1]))
					j = j - 1;
				else j = j - 2;
				x = getIndex(s[j]);
				y = getIndex(q);
			} while (Data[x][y] != '<');
			int m, n, N;
			for (m = j + 1; m <= k; m++)
			{
				for (N = 0; N<r1; N++)
					for (n = 1; In_str[N][n] != '\0'; n++)
					{
						if (!Terminator(s[m]) && !Terminator(In_str[N][n]))
						{
							if (Terminator(s[m + 1]) && Terminator(In_str[N][n + 1])
								&& s[m + 1] == In_str[N][n + 1])
							{
								s[j + 1] = In_str[N][0];
								break;
							}
						}
						else
							if (Terminator(s[m]))
								if (s[m] == In_str[N][n])
								{
									s[j + 1] = In_str[N][0];
									break;
								}
					}
			}
			k = j + 1;
			if (k == 2 && a == '#')
			{
				out(1, k, s);
				printf("%c", a);
				out(i + 1, z, input);
				printf("结束\n");
				printf("\n输入串符合文法的定义!\n");
				return 1;                               //输入串符合文法的定义
			}
		}
		else
			if (Data[x][y] == '<' || Data[x][y] == '=')
			{                                                //移进
				out(1, k, s);
				printf("%c", a);
				out(i + 1, z, input);
				printf("移进\n");
				k++;
				s[k] = a;
				i++;
			}
			else
			{
				printf("\n输入串不符合文法的定义!\n");
				return 0;
			}
	}
	printf("\n输入串不符合文法的定义!\n");
	return 0;
}
 
void out(int j, int k, char *s)
{
	int n = 0;
	int i;
	for (i = j; i <= k; i++)
	{
		printf("%c", s[i]);
		n++;
	}
	for (; n<15; n++)
	{
		printf(" ");
	}
}
 
int getIndex(char c)                           //求字符c在文法终极符表中的下标
{
	int i;
	for (i = 0; lable[i] != '\0'; i++)
	{
		if (c == lable[i])
			return i;
	}
	return -1;
}
 
int Terminator(char c)                            //判断字符c是否是终极符
{
	int i;
	for (i = 0; lable[i] != '\0'; i++)
	{
		if (c == lable[i])
			return 1;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40912854/article/details/92583523
今日推荐