编译原理 预测分析法

实验二 预测分析算法的设计与实现

一、实验目的

通过预测分析算法的设计与实现,加深对自上而下语法分析方法的理解,尤其是对自上而下分析条件的理解。

二、实验要求

输入文法及待分析的输入串,输出其预测分析过程及结果。

三、实验步骤

1、确定目标数据结构

先看下输入的文法结构

E->TK
K->+TK|$
T->FM
M->*FM|$
F->i|(E)
#

$代表空,#代表结束

将文法使用具体的数据结构描述出来使用C++好像只有结构体有可操作性了。所以我果断使用结构体。用一个结构体代表一个非终结符的所有产生式,该终结符的所有产生式之间使用‘|’隔开。
废话不多说,直接上代码

struct Node
{
	char Left;
	int RightCount;
	char Right[100][100];
	int FirstCount;
	int FollowCount;
	char First[100];
	char Follow[100];
};

Node GrammerSet[100];

接下来再定义这下数据

int grammersetcount = 0;
int tersymbolcount = 0;//终结符数量
int nontercount = 0;//非终结符数量  默认第一个非终结符为开始符号
char TerSymbol[200];//终结符 非大写字母
map<char, bool> isfirsted;//该终结符是否已经求过其first集
bool isfollowed[200];
char Non_Ter[200];//非终结符 大写字母
char AllSymbol[400];//所有符号

grammersetcount在数值上等于nontercount。

2、读入数据

这个没啥好说的,直接读就行。另外注意字符数组的初始化。

void ReadGrammerSet()
{
	char str[100];
	while (1)
	{
		cin >> str;
		if (str[0] == '#')
			break;
		GrammerSet[grammersetcount].Left = str[0];
		SymbolProcess(str[0]);//处理左边的
		for (int i = 3;i<strlen(str); i++)
		{
			
			int j = 0;
			char str2[100];
			while ((str[i] != '|')&&(str[i]!='\0'))
			{
				SymbolProcess(str[i]);//处理右边的
				str2[j++] = str[i++];
			}
			str2[j] = '\0';
			strcpy_s(GrammerSet[grammersetcount].Right[GrammerSet[grammersetcount].RightCount], str2);
			GrammerSet[grammersetcount].RightCount++;
		}
		grammersetcount++;
	}
}

3、求first集

first集就是一个非终结符所能推出的式子中第一个终结符的集合就是这个非终结符的first集。广义上来讲,对于一个终结符来讲,它的first集就是他本身。对于一个串来讲,他的first集就是从这个串中第一个字符开始,将这个字符的first集并入这个字符串的first集,若这个字符的first集中有$,则指向下一个字符,否则break。直到遍历完这个串。
知道了first集究竟是个什么之后,就很容易想到求解的方法。就是拿着一个产生式进行遍历推到罢了。
上代码

void First(char sym)
{
	//cout << "正在查找" << sym << "的first集" << endl;
	int i;
	for (i = 0; i < grammersetcount; i++)
	{
		if (GrammerSet[i].Left == sym)//找到这个非终结符所在产生式的位置
			break;
	}
	for (int j = 0; j < GrammerSet[i].RightCount; j++)
	{
		//如果first(ch)中包含$,则ch=它的下一个字符 否则退出这个循环
		int shouldbreak = 1;
		for (int pos = 0; pos < strlen(GrammerSet[i].Right[j]); pos++)
		{
			//产生式右部第一个字符为终结符,将其计入左部first集
			char ch = GrammerSet[i].Right[j][pos];
			//cout << "正在判断" << ch << endl;
			if (isTerSymbol(ch))
			{
				//是否已经收录过
				int flag = 0;
				for (int k = 0; k < GrammerSet[i].FirstCount; k++)
				{
					if (GrammerSet[i].First[k] == ch)
					{
						flag = 1;//已收录
						break;
					}
				}
				if (flag == 0)//未收录
					GrammerSet[i].First[GrammerSet[i].FirstCount++] = ch;
			}
			else//非终结符,求该非终结符的first集 如果first(ch)中包含$,则ch=它的下一个字符
			{
				//if(isfirsted(ch)==false)
				First(ch);
				//如果first(ch)中包含$,则ch=它的下一个字符 如果已经是最后一个字符,则程序还是会自动退出循环
				int i;
				for (i = 0; i < grammersetcount; i++)
				{
					if (GrammerSet[i].Left == ch)//找到这个非终结符所在产生式的位置
						break;
				}
				int flag = 0;
				for (int position = 0; position < GrammerSet[i].FirstCount; position++)
				{
					if (GrammerSet[i].First[position] == '$')
					{
						flag = 1;//包含$
						break;
					}
				}
				if (flag == 1)//包含$ ch=它的下一个字符 不应该推出循环
				{
					shouldbreak = 0;
				}
				//将ch的first集并入sym非终结符
				AddFirst(sym, ch);
			}
			if (shouldbreak == 1)
			{
				break;
			}
		}
	}
	//cout << "已经查找完成" << sym << "的first集为"<<GrammerSet[i].First<<endl;
}

4、求follow集

对于一个非终结符来讲,follow就是这个非终结符在这个文法所能推导出的所有式子中在它后面的那个字符的集合。
有以下两种情况。
1: A–>”a"B
2: A->“a"B"b”
其中“a"与”b"都代表一个可以为空的串。
1,经过这个产生式的推到之后,可以知道,A后面跟着的那个肯定也跟着B,但是反过来就不一定了。所以将follow(A)并入Follow(B)
2: 与1差不多,不过要与first集联系起来懒得说了,直接上图吧。这个是前两天写的,看看就好。在这里插入图片描述
还是看代码比较省力

void Follow(char sym)
{
//	cout << "正在寻找" << sym << "的follow集" << endl;
	//对全部的产生式找一个右部含有当前字符sym的产生式
	for (int i = 0; i < grammersetcount; i++)
	{
		for (int j = 0; j < GrammerSet[i].RightCount; j++)
		{
			for (int k = 0; k < strlen(GrammerSet[i].Right[j]); k++)
			{
				//找到一个右部含有当前字符sym的产生式
				if (GrammerSet[i].Right[j][k] == sym)
				{
					//如果sym在产生式右部的最后(形如产生式A->aX)
					//X的follow不一定是A的,但是A的一定是X的。
					if (strlen(GrammerSet[i].Right[j]) - 1 == k)
					{
						char ch = GrammerSet[i].Left;
						if (sym != ch)
						{
							//求ch 的follow
							if (!isfollowed[ch])
								Follow(ch);
							//把FOLLOW(ch)中的元素加入FOLLOW(X)
							AddFollow(sym, ch);
						}
					}
					//if X不在产生式右部的最后(A->aXB) B在这里代表一个符号串
					else
					{
						//遍历B中所有字符
						for (int r = k + 1; r < strlen(GrammerSet[i].Right[j]); r++)
						{
							char ch = GrammerSet[i].Right[j][r];
							//是终结符  加入follow(sym)
							if (isTerSymbol(ch))
							{
								AddCharToFollow(sym, ch);
								break;
							}
							else
							{
								//将first(ch)加入follow(sym)
								AddFirstToFollow(sym, ch);
								if (!hasnullinfirst(ch))
								{
									break;
								}
								//如果ch的first含有空值且sym!=ch则将ch的follow并入follow(sym)
								if(sym!=ch)
								{
									if (isfollowed[ch])
										AddFollow(sym, ch);
									else
										Follow(ch);
								}
							}
						}
					}
				}
			}
		}
	}
	isfollowed[sym] = 1;
//	cout << "已经完成寻找" << sym << "的follow集" << endl;
}

5、构造分析预测表

这个没啥好说的,按书上的方法来就行。懒得说了。在这里插入图片描述
注意阿尔法与a。别弄错了。

void CreateForecastTable()
{
	//初始化预测表
	int $pos = -1;//不是每一种文法都有空
	length1 = nontercount;//有几个非终结符就有几行
	length2 = tersymbolcount;//列
	for (int i = 0; i < grammersetcount; i++)//注意从一开始
		ForcastTable[i + 1][0][0] = GrammerSet[i].Left;
	for (int j = 0; j < tersymbolcount; j++)
	{
		if (TerSymbol[j] == '$')
		{
			ForcastTable[0][j + 1][0] = '#';
			$pos = j + 1;
		}
		else
			ForcastTable[0][j + 1][0] = TerSymbol[j];
//		cout << TerSymbol[j] << "---------------------------" << endl;
	}
	if ($pos != -1)//不是每一种文法都有空   这个文法有空
	{
		ForcastTable[0][$pos][0] = TerSymbol[tersymbolcount - 1];
		ForcastTable[0][tersymbolcount][0] = '#';
	}
	else//这个文法没有空
	{
		ForcastTable[0][tersymbolcount + 1][0] = '#';
		length2++;//没有空则列数要加1
	}

	//遍历所有的产生式
	for (int i = 0; i < grammersetcount; i++)
	{
		for (int j = 0; j < GrammerSet[i].RightCount; j++)
		{
			for (int ll = 0; ll < 100; ll++)
				str_fir[ll] = '\0';
			//遍历串  
			for (int k = 0; k < strlen(GrammerSet[i].Right[j]); k++)
			{
				char ch = GrammerSet[i].Right[j][k];
				//非终结符
				if (!isTerSymbol(ch))
				{
					int pos = 0;
					for (pos = 0; pos < grammersetcount; pos++)
						if (GrammerSet[pos].Left == ch)
							break;
					for (int r = 0; r <= strlen(GrammerSet[pos].First); r++)
					{
						int strlength = strlen(str_fir);
						str_fir[strlength] = GrammerSet[pos].First[r];
						str_fir[strlength + 1] = '\0';
					}
					if (!hasnullinfirst(ch))
						break;
				}
				else//终结符
				{
					int strlength = strlen(str_fir);
					str_fir[strlength] = ch;
					str_fir[strlength + 1] = '\0';
					break;
				}
			}
//			cout << GrammerSet[i].Right[j] << "的first集为" << str_fir << endl;
			int flag = 0;
			for(int k=0;k<strlen(str_fir);k++)
				if (str_fir[k] == '$')
				{
					flag = 1;
					break;
				}
			//有空,则进行follow的处理
			if (flag == 1)
			{
				//A=GrammerSet[i].Left;
				//遍历follow
				for (int k = 0; k < GrammerSet[i].FollowCount; k++)
				{
					char ch = GrammerSet[i].Follow[k];
					int pos1 = 0;
					int pos2 = 0;
					for (pos1 = 0; pos1 <= length1; pos1++)
						if (ForcastTable[pos1][0][0] == GrammerSet[i].Left)
							break;
					for (pos2 = 0; pos2 <= length2; pos2++)
						if (ForcastTable[0][pos2][0] == ch)
							break;
					//添加 A->串
					char s[100];
					strcpy_s(s, "A->");
					strcat_s(s, GrammerSet[i].Right[j]);
					s[0] = GrammerSet[i].Left;
					strcpy_s(ForcastTable[pos1][pos2], s);
				//	cout << "follow-------------------------------" << endl;
				}
			}
			//对first(串)中的每一个字符进行处理
			for (int k = 0; k < strlen(str_fir); k++)
			{
				char ch = str_fir[k];
				int pos1 = 0;
				int pos2 = 0;
				for (pos1 = 0; pos1 <= length1; pos1++)
					if (ForcastTable[pos1][0][0] == GrammerSet[i].Left)
						break;
				for (pos2 = 0; pos2 <= length2; pos2++)
					if (ForcastTable[0][pos2][0] == ch)
						break;
				//添加 A->串
				char s[100];
				strcpy_s(s, "A->");
				strcat_s(s, GrammerSet[i].Right[j]);
				s[0] = GrammerSet[i].Left;
				strcpy_s(ForcastTable[pos1][pos2], s);
			}
		}
	}
}

6、构造总控程序

这个是整个实验中最简单的一步了。我不废话了。

void MainControlProcess()
{
	
	ReadInput();
	stack<char>Stack;
	Stack.push('#');
	Stack.push(GrammerSet[0].Left);
	int flag = 0;
	char X;
	char a;
	char instack[100];
	int posstack = 0;
	int pos = 0;
	int step = 0;
	for (int i = 0; i < 100; i++)
		instack[i] = '\0';
	instack[0] = '#';
	instack[1] = GrammerSet[0].Left;
	posstack = 1;
	cout << endl;
	while (1)
	{
		cout << step++ << "   ";
		a = text[pos];
		X=Stack.top();//获取栈顶元素
		cout << "X=" << X << " a=" << a<<"   ";
		cout << "符号栈:" << instack << "     ";
		cout << "输入串:";
		for (int i = pos; i < strlen(text); i++)
			cout << text[i];
		Stack.pop();
		instack[posstack] = '\0';
		posstack--;
		if (X == '#')//结束
		{
			if (a=='#')
			{
				flag = 1;
				cout << "successful" << flag << endl;
				return;
			}
			else
			{
				flag = -1;
				cout << "匹配失败" << flag << endl;
			}
		}
		else if (isTerSymbol(X))//终结符 匹配
		{
		//	cout << "终结符匹配" << X << a << endl;
			if (X == a)
			{
				pos++;
				a = text[pos];
			}
			else
			{
				flag = -2;
				cout << "error" << flag << endl;
				return;
			}
		}
		else//使用规则进行匹配
		{
			int pos1 = 0;
			int pos2 = 0;
			for (pos1 = 0; pos1 <= length1; pos1++)
				if (ForcastTable[pos1][0][0] == X)
					break;
			for (pos2 = 0; pos2 <= length2; pos2++)
				if (ForcastTable[0][pos2][0] == a)
					break;
			char ch;
			for (int i = strlen(ForcastTable[pos1][pos2])-1; i >= 3; i--)
			{
				ch = ForcastTable[pos1][pos2][i];
				if (ch == '$')
					break;
				if (ch == '\0')
				{
					flag = -3;
					cout << "error" << flag << endl;
					return;
				}
				Stack.push(ch);
				instack[++posstack] = ch;
			}
			//这里是使用产生式 书上是所用产生式,不一样 哈哈哈哈哈哈哈哈哈
			cout << "使用产生式:" << ForcastTable[pos1][pos2];
		}
		cout << endl;
	}
}

7、结果

在这里插入图片描述
不太好看,不过算了。
其中最后读取的那个要分析的串在example.txt中。
我的内容是
i*i+i#书上一样

8、代码



#include <iostream>
#include <fstream>
#include <stack>
#include <map>

using namespace std;

int grammersetcount = 0;
int tersymbolcount = 0;//终结符数量
int nontercount = 0;//非终结符数量  默认第一个非终结符为开始符号
char TerSymbol[200];//终结符 非大写字母
map<char, bool> isfirsted;//该终结符是否已经求过其first集
bool isfollowed[200];
char Non_Ter[200];//非终结符 大写字母
char AllSymbol[400];//所有符号
char ForcastTable[100][100][100];
int length1 = nontercount;//有几个非终结符就有几行
int length2 = tersymbolcount;//列
char str_fir[100];//求出first(串) GrammerSet[i].Right[j];
char text[1000];//输入要处理的字符串
struct Node
{
	char Left;
	int RightCount;
	char Right[100][100];
	int FirstCount;
	int FollowCount;
	char First[100];
	char Follow[100];
};

Node GrammerSet[100];
void ShowGrammerSet(Node Grammer[]);//打印全部产生式
void ReadGrammerSet();
bool isTerSymbol(char ch);//true为终结符false为非终结符
void SymbolProcess(char ch);//字符归类
void First(char sym);
void AddFirst(char sym, char ch);//并入first集
void Follow(char sym);
void AddFollow(char sym, char  ch);
void AddFirstToFollow(char sym, char  ch);//将ch的first加入sym的follow中
void AddCharToFollow(char sym, char  ch);//将ch加入sym的follow中
bool hasnullinfirst(char ch);//判断一个非终结符的first中是否有空
void CreateForecastTable();
void ShowForecastTable();
void ReadInput();//读入
void MainControlProcess();//主控程序

int main()
{
	ReadGrammerSet();
//	cout << "first___________________________________" << endl;
	for (int i = 0; i < grammersetcount; i++)
	{
		First(GrammerSet[i].Left);
	//	cout <<GrammerSet[i].Left<<" "<< GrammerSet[i].First << endl;
	}
//	cout << "follow___________________________________" << endl;
	for (int i = 0; i < grammersetcount; i++)
	{
	//	cout << i<<"main函数这里要去寻找" << GrammerSet[i].Left << "的follow集了" << endl;
		Follow(GrammerSet[i].Left);
	//	cout << GrammerSet[i].Left << " " << GrammerSet[i].Follow << endl;
	}
	//将# 加入到follow(x)中
//	cout << "为开始符号将# 加入到follow(x)中" << endl;
	for (int i = 0; i < grammersetcount; i++)
		GrammerSet[i].Follow[GrammerSet[i].FollowCount++] = '#';
	ShowGrammerSet(GrammerSet);
	cout << "first----------------------------------------------------------------------------" << endl;
	for (int i = 0; i < grammersetcount; i++)
		cout << GrammerSet[i].Left << " " << GrammerSet[i].FirstCount << " " << GrammerSet[i].First << endl;
	cout << "follow----------------------------------------------------------------------------" << endl;
	for (int i = 0; i < grammersetcount; i++)
		cout << GrammerSet[i].Left << " " << GrammerSet[i].FollowCount << " " << GrammerSet[i].Follow << endl;
	CreateForecastTable();
	ShowForecastTable();
	MainControlProcess();
}
void ShowGrammerSet(Node GrammerSet[])
{
	/*
	for (int i = 0; i < grammersetcount; i++)
	{
		cout << i << "   " << GrammerSet[i].Left << endl;
		for (int j = 0; j < GrammerSet[i].RightCount; j++)
			cout << j << "   " << GrammerSet[i].Right[j] << endl;
	}
	cout << "非终结符的数量" << nontercount << endl;
	cout << "非终结符" << endl;
	for (int i = 0; i <nontercount; i++)
		cout << Non_Ter[i]<<" ";
	cout << endl;
	cout << "终结符的数量" << tersymbolcount << endl;
	cout << "终结符" << endl;
	for (int i = 0; i < tersymbolcount; i++)
		cout << TerSymbol[i]<<" ";
	cout << endl;
	
	for (int i = 0; i < grammersetcount; i++)
	{
		for (int j = 0; j < GrammerSet[i].RightCount; j++)
		{
			cout << GrammerSet[i].Left << "->" << GrammerSet[i].Right[j] << endl;
		}
	}
	*/
}
void ReadGrammerSet()
{
	char str[100];
	while (1)
	{
		cin >> str;
		if (str[0] == '#')
			break;
		GrammerSet[grammersetcount].Left = str[0];
		SymbolProcess(str[0]);//处理左边的
		for (int i = 3;i<strlen(str); i++)
		{
			
			int j = 0;
			char str2[100];
			while ((str[i] != '|')&&(str[i]!='\0'))
			{
				SymbolProcess(str[i]);//处理右边的
				str2[j++] = str[i++];
			}
			str2[j] = '\0';
			strcpy_s(GrammerSet[grammersetcount].Right[GrammerSet[grammersetcount].RightCount], str2);
			GrammerSet[grammersetcount].RightCount++;
		}
		grammersetcount++;
	}
}
bool isTerSymbol(char ch)
{
//	cout << "正在判断"<<ch<<"是否为终结符" << endl;
	if ( ch >= 'A' && ch <= 'Z')
		return false;
	return true;
}
void SymbolProcess(char ch)
{
	//非终结符
	if (ch <= 'Z' && ch>='A')
	{
		int flag = 0;
		for (int i = 0; i < nontercount; i++)
		{
			if (ch == Non_Ter[i])
			{
				flag = 1;
				break;//已收录
			}
		}
		if (flag == 0)
		{
			Non_Ter[nontercount++] = ch;
			isfirsted.insert(pair<char, bool>(ch, false));
		}
	}
	else//终结符
	{
		int flag = 0;
		for (int i = 0; i < tersymbolcount; i++)
		{
			if (ch == TerSymbol[i])
			{
				flag = 1;
				break;//已收录
			}
		}
		if (flag == 0)
		{
			TerSymbol[tersymbolcount++] = ch;
		}
	}
}
void First(char sym)
{
	//cout << "正在查找" << sym << "的first集" << endl;
	int i;
	for (i = 0; i < grammersetcount; i++)
	{
		if (GrammerSet[i].Left == sym)//找到这个非终结符所在产生式的位置
			break;
	}
	for (int j = 0; j < GrammerSet[i].RightCount; j++)
	{
		//如果first(ch)中包含$,则ch=它的下一个字符 否则退出这个循环
		int shouldbreak = 1;
		for (int pos = 0; pos < strlen(GrammerSet[i].Right[j]); pos++)
		{
			//产生式右部第一个字符为终结符,将其计入左部first集
			char ch = GrammerSet[i].Right[j][pos];
			//cout << "正在判断" << ch << endl;
			if (isTerSymbol(ch))
			{
				//是否已经收录过
				int flag = 0;
				for (int k = 0; k < GrammerSet[i].FirstCount; k++)
				{
					if (GrammerSet[i].First[k] == ch)
					{
						flag = 1;//已收录
						break;
					}
				}
				if (flag == 0)//未收录
					GrammerSet[i].First[GrammerSet[i].FirstCount++] = ch;
			}
			else//非终结符,求该非终结符的first集 如果first(ch)中包含$,则ch=它的下一个字符
			{
				//if(isfirsted(ch)==false)
				First(ch);
				//如果first(ch)中包含$,则ch=它的下一个字符 如果已经是最后一个字符,则程序还是会自动退出循环
				int i;
				for (i = 0; i < grammersetcount; i++)
				{
					if (GrammerSet[i].Left == ch)//找到这个非终结符所在产生式的位置
						break;
				}
				int flag = 0;
				for (int position = 0; position < GrammerSet[i].FirstCount; position++)
				{
					if (GrammerSet[i].First[position] == '$')
					{
						flag = 1;//包含$
						break;
					}
				}
				if (flag == 1)//包含$ ch=它的下一个字符 不应该推出循环
				{
					shouldbreak = 0;
				}
				//将ch的first集并入sym非终结符
				AddFirst(sym, ch);
			}
			if (shouldbreak == 1)
			{
				break;
			}
		}
	}
	//cout << "已经查找完成" << sym << "的first集为"<<GrammerSet[i].First<<endl;
}
void AddFirst(char sym, char ch)//并入first集 将ch的first集并入sym的first集
{
	//cout << "正在将" << ch << "的first集并入" << sym << "的first集" << endl;
	int p1 = 0;
	int p2 = 0;
	int pos1 = 0;
	int pos2 = 0;
	for (pos1 = 0; pos1 < grammersetcount; pos1++)
	{
		if (GrammerSet[pos1].Left == sym)
			break;
	}
	for (pos2 = 0; pos2 < grammersetcount; pos2++)
	{
		if (GrammerSet[pos2].Left == ch)
			break;
	}
	//cout << sym << "的first集为" << GrammerSet[pos1].First << endl;
	//cout << ch << "的first集为" << GrammerSet[pos2].First << endl;
	for (p2 = 0; p2 < GrammerSet[pos2].FirstCount; p2++)
	{
		int flag = 0;
		for (int p1 = 0; p1 < GrammerSet[pos1].FirstCount; p1++)
		{
			if (GrammerSet[pos1].First[p1] == GrammerSet[pos2].First[p2])
			{
				flag = 1;
				break;
			}
		}
		if (flag == 0)
		{
			GrammerSet[pos1].First[GrammerSet[pos1].FirstCount++] = GrammerSet[pos2].First[p2];
		}
	}
	//cout << "完成并入" << endl;
	//cout << sym << "的first集为" << GrammerSet[pos1].First << endl;
	//cout << ch << "的first集为" << GrammerSet[pos2].First << endl;
}
void Follow(char sym)
{
//	cout << "正在寻找" << sym << "的follow集" << endl;
	//对全部的产生式找一个右部含有当前字符sym的产生式
	for (int i = 0; i < grammersetcount; i++)
	{
		for (int j = 0; j < GrammerSet[i].RightCount; j++)
		{
			for (int k = 0; k < strlen(GrammerSet[i].Right[j]); k++)
			{
				//找到一个右部含有当前字符sym的产生式
				if (GrammerSet[i].Right[j][k] == sym)
				{
					//如果sym在产生式右部的最后(形如产生式A->aX)
					//X的follow不一定是A的,但是A的一定是X的。
					if (strlen(GrammerSet[i].Right[j]) - 1 == k)
					{
						char ch = GrammerSet[i].Left;
						if (sym != ch)
						{
							//求ch 的follow
							if (!isfollowed[ch])
								Follow(ch);
							//把FOLLOW(ch)中的元素加入FOLLOW(X)
							AddFollow(sym, ch);
						}
					}
					//if X不在产生式右部的最后(A->aXB) B在这里代表一个符号串
					else
					{
						//遍历B中所有字符
						for (int r = k + 1; r < strlen(GrammerSet[i].Right[j]); r++)
						{
							char ch = GrammerSet[i].Right[j][r];
							//是终结符  加入follow(sym)
							if (isTerSymbol(ch))
							{
								AddCharToFollow(sym, ch);
								break;
							}
							else
							{
								//将first(ch)加入follow(sym)
								AddFirstToFollow(sym, ch);
								if (!hasnullinfirst(ch))
								{
									break;
								}
								//如果ch的first含有空值且sym!=ch则将ch的follow并入follow(sym)
								if(sym!=ch)
								{
									if (isfollowed[ch])
										AddFollow(sym, ch);
									else
										Follow(ch);
								}
							}
						}
					}
				}
			}
		}
	}
	isfollowed[sym] = 1;
//	cout << "已经完成寻找" << sym << "的follow集" << endl;
}
void AddFollow(char sym, char  ch)
{
//	cout << "正在将" << ch << "的Follow集并入" << sym << "的Follow集" << endl;
	int p1 = 0;
	int p2 = 0;
	int pos1 = 0;
	int pos2 = 0;
	for (pos1 = 0; pos1 < grammersetcount; pos1++)
	{
		if (GrammerSet[pos1].Left == sym)
			break;
	}
	for (pos2 = 0; pos2 < grammersetcount; pos2++)
	{
		if (GrammerSet[pos2].Left == ch)
			break;
	}
//	cout << sym << "的Follow集为" << GrammerSet[pos1].Follow << endl;
//	cout << ch << "的Follow集为" << GrammerSet[pos2].Follow << endl;
	for (p2 = 0; p2 < GrammerSet[pos2].FollowCount; p2++)
	{
		int flag = 0;
		for (int p1 = 0; p1 < GrammerSet[pos1].FollowCount; p1++)
		{
			if (GrammerSet[pos1].Follow[p1] == GrammerSet[pos2].Follow[p2])
			{
				flag = 1;
				break;
			}
		}
		if (flag == 0)
		{
			GrammerSet[pos1].Follow[GrammerSet[pos1].FollowCount++] = GrammerSet[pos2].Follow[p2];
		}
	}
//	cout << "完成并入" << endl;
//	cout << sym << "的Follow集为" << GrammerSet[pos1].Follow << endl;
//	cout << ch << "的Follow集为" << GrammerSet[pos2].Follow << endl;
}
void AddFirstToFollow(char sym, char  ch)
{
//	cout << "正在将" << ch << "的First集并入" << sym << "的Follow集" << endl;
	int p1 = 0;
	int p2 = 0;
	int pos1 = 0;
	int pos2 = 0;
	for (pos1 = 0; pos1 < grammersetcount; pos1++)
	{
		if (GrammerSet[pos1].Left == sym)
			break;
	}
	for (pos2 = 0; pos2 < grammersetcount; pos2++)
	{
		if (GrammerSet[pos2].Left == ch)
			break;
	}
//	cout << sym << "的Follow集为" << GrammerSet[pos1].Follow << endl;
//	cout << ch << "的First集为" << GrammerSet[pos2].First << endl;
	for (p2 = 0; p2 < GrammerSet[pos2].FirstCount; p2++)
	{
		int flag = 0;
		for (int p1 = 0; p1 < GrammerSet[pos1].FollowCount; p1++)
		{
			if (GrammerSet[pos1].Follow[p1] == GrammerSet[pos2].First[p2])
			{
				flag = 1;
				break;
			}
		}
		if ((flag == 0)&&(GrammerSet[pos2].First[p2]!='$'))
		{
			GrammerSet[pos1].Follow[GrammerSet[pos1].FollowCount++] = GrammerSet[pos2].First[p2];
		}
	}
//	cout << "完成并入" << endl;
//	cout << sym << "的Follow集为" << GrammerSet[pos1].Follow << endl;
//	cout << ch << "的First集为" << GrammerSet[pos2].First << endl;
}
void AddCharToFollow(char sym, char  ch)
{
	if (ch == '$')
		return;
//	cout << "正在将字符" << ch << "并入"<<sym<<"的follow集中" << endl;
	int pos = 0;
	for (pos = 0; pos < grammersetcount; pos++)
	{
		if (GrammerSet[pos].Left == sym)
			break;
	}
	int flag = 0;
	for (int i = 0; i < strlen(GrammerSet[pos].Follow); i++)
	{
		if (GrammerSet[pos].Follow[i] == 'ch')
		{
			flag = 1;
			break;
		}
	}
	if (flag == 0)
	{
		GrammerSet[pos].Follow[GrammerSet[pos].FollowCount++] = ch;
	}
}
bool hasnullinfirst(char ch)
{
//	cout << "正在查找" << ch << "的first集中是否有空" << endl;
	int pos = 0;
	for (pos = 0; pos < grammersetcount; pos++)
	{
		if (GrammerSet[pos].Left == ch)
			break;
	}
	int flag = 0;
	for (int i = 0; i < strlen(GrammerSet[pos].First); i++)
	{
		if (GrammerSet[pos].First[i] == '$')
		{
			flag = 1;
			break;
		}
	}
//	if(flag==1)
//		cout << ch << "的first集中有空" << endl;
//	else
//		cout << ch << "的first集中没有空" << endl;
	return flag;
}
void CreateForecastTable()
{
	//初始化预测表
	int $pos = -1;//不是每一种文法都有空
	length1 = nontercount;//有几个非终结符就有几行
	length2 = tersymbolcount;//列
	for (int i = 0; i < grammersetcount; i++)//注意从一开始
		ForcastTable[i + 1][0][0] = GrammerSet[i].Left;
	for (int j = 0; j < tersymbolcount; j++)
	{
		if (TerSymbol[j] == '$')
		{
			ForcastTable[0][j + 1][0] = '#';
			$pos = j + 1;
		}
		else
			ForcastTable[0][j + 1][0] = TerSymbol[j];
//		cout << TerSymbol[j] << "---------------------------" << endl;
	}
	if ($pos != -1)//不是每一种文法都有空   这个文法有空
	{
		ForcastTable[0][$pos][0] = TerSymbol[tersymbolcount - 1];
		ForcastTable[0][tersymbolcount][0] = '#';
	}
	else//这个文法没有空
	{
		ForcastTable[0][tersymbolcount + 1][0] = '#';
		length2++;//没有空则列数要加1
	}

	//遍历所有的产生式
	for (int i = 0; i < grammersetcount; i++)
	{
		for (int j = 0; j < GrammerSet[i].RightCount; j++)
		{
			for (int ll = 0; ll < 100; ll++)
				str_fir[ll] = '\0';
			//遍历串  
			for (int k = 0; k < strlen(GrammerSet[i].Right[j]); k++)
			{
				char ch = GrammerSet[i].Right[j][k];
				//非终结符
				if (!isTerSymbol(ch))
				{
					int pos = 0;
					for (pos = 0; pos < grammersetcount; pos++)
						if (GrammerSet[pos].Left == ch)
							break;
					for (int r = 0; r <= strlen(GrammerSet[pos].First); r++)
					{
						int strlength = strlen(str_fir);
						str_fir[strlength] = GrammerSet[pos].First[r];
						str_fir[strlength + 1] = '\0';
					}
					if (!hasnullinfirst(ch))
						break;
				}
				else//终结符
				{
					int strlength = strlen(str_fir);
					str_fir[strlength] = ch;
					str_fir[strlength + 1] = '\0';
					break;
				}
			}
//			cout << GrammerSet[i].Right[j] << "的first集为" << str_fir << endl;
			int flag = 0;
			for(int k=0;k<strlen(str_fir);k++)
				if (str_fir[k] == '$')
				{
					flag = 1;
					break;
				}
			//有空,则进行follow的处理
			if (flag == 1)
			{
				//A=GrammerSet[i].Left;
				//遍历follow
				for (int k = 0; k < GrammerSet[i].FollowCount; k++)
				{
					char ch = GrammerSet[i].Follow[k];
					int pos1 = 0;
					int pos2 = 0;
					for (pos1 = 0; pos1 <= length1; pos1++)
						if (ForcastTable[pos1][0][0] == GrammerSet[i].Left)
							break;
					for (pos2 = 0; pos2 <= length2; pos2++)
						if (ForcastTable[0][pos2][0] == ch)
							break;
					//添加 A->串
					char s[100];
					strcpy_s(s, "A->");
					strcat_s(s, GrammerSet[i].Right[j]);
					s[0] = GrammerSet[i].Left;
					strcpy_s(ForcastTable[pos1][pos2], s);
				//	cout << "follow-------------------------------" << endl;
				}
			}
			//对first(串)中的每一个字符进行处理
			for (int k = 0; k < strlen(str_fir); k++)
			{
				char ch = str_fir[k];
				int pos1 = 0;
				int pos2 = 0;
				for (pos1 = 0; pos1 <= length1; pos1++)
					if (ForcastTable[pos1][0][0] == GrammerSet[i].Left)
						break;
				for (pos2 = 0; pos2 <= length2; pos2++)
					if (ForcastTable[0][pos2][0] == ch)
						break;
				//添加 A->串
				char s[100];
				strcpy_s(s, "A->");
				strcat_s(s, GrammerSet[i].Right[j]);
				s[0] = GrammerSet[i].Left;
				strcpy_s(ForcastTable[pos1][pos2], s);
			}
		}
	}
}
void ShowForecastTable()
{
	for (int i = 0; i <=length1; i++)
	{
		for (int j = 0; j <= length2; j++)
		{
			cout << ForcastTable[i][j];
			for (int k = 0; k < 10 - strlen(ForcastTable[i][j]); k++)
				cout << ".";
		}
		cout << endl << endl;
	}
}
void ReadInput()
{
	int pos = 0;
	ifstream fin;
	fin.open("example.txt");
	while (!fin.eof())
	{
		text[pos++] = fin.get();
	}
	fin.close();
	cout << text;
	pos = 0;
}
void MainControlProcess()
{
	
	ReadInput();
	stack<char>Stack;
	Stack.push('#');
	Stack.push(GrammerSet[0].Left);
	int flag = 0;
	char X;
	char a;
	char instack[100];
	int posstack = 0;
	int pos = 0;
	int step = 0;
	for (int i = 0; i < 100; i++)
		instack[i] = '\0';
	instack[0] = '#';
	instack[1] = GrammerSet[0].Left;
	posstack = 1;
	cout << endl;
	while (1)
	{
		cout << step++ << "   ";
		a = text[pos];
		X=Stack.top();//获取栈顶元素
		cout << "X=" << X << " a=" << a<<"   ";
		cout << "符号栈:" << instack << "     ";
		cout << "输入串:";
		for (int i = pos; i < strlen(text); i++)
			cout << text[i];
		Stack.pop();
		instack[posstack] = '\0';
		posstack--;
		if (X == '#')//结束
		{
			if (a=='#')
			{
				flag = 1;
				cout << "successful" << flag << endl;
				return;
			}
			else
			{
				flag = -1;
				cout << "匹配失败" << flag << endl;
			}
		}
		else if (isTerSymbol(X))//终结符 匹配
		{
		//	cout << "终结符匹配" << X << a << endl;
			if (X == a)
			{
				pos++;
				a = text[pos];
			}
			else
			{
				flag = -2;
				cout << "error" << flag << endl;
				return;
			}
		}
		else//使用规则进行匹配
		{
			int pos1 = 0;
			int pos2 = 0;
			for (pos1 = 0; pos1 <= length1; pos1++)
				if (ForcastTable[pos1][0][0] == X)
					break;
			for (pos2 = 0; pos2 <= length2; pos2++)
				if (ForcastTable[0][pos2][0] == a)
					break;
			char ch;
			for (int i = strlen(ForcastTable[pos1][pos2])-1; i >= 3; i--)
			{
				ch = ForcastTable[pos1][pos2][i];
				if (ch == '$')
					break;
				if (ch == '\0')
				{
					flag = -3;
					cout << "error" << flag << endl;
					return;
				}
				Stack.push(ch);
				instack[++posstack] = ch;
			}
			//这里是使用产生式 书上是所用产生式,不一样 哈哈哈哈哈哈哈哈哈
			cout << "使用产生式:" << ForcastTable[pos1][pos2];
		}
		cout << endl;
	}
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值