编译原理—实验三 LL(1)语法分析(二)

版权声明:欢迎转载 https://blog.csdn.net/wl1780852311/article/details/90054485

实验三 LL(1)语法分析(二)(2学时)
一、实验目的
1.熟悉LL(1)语法分析的基本原理,语法分析的过程,以及语法分析中要注意的一些问题。
2. 复习高级语言及线性表、栈、图等典型数据结构,进一步加强用高级语言来解决实际问题的能力。
二、实验内容
将实验二编写的程序的基础之上,实现下面的功能:
按照教材5.2节算法,求出各个非终结符的first集和follow集并采用适当的数据结构存储,并在屏幕上显示结果。
算法描述
求非终结符的first集
扫描以要求first集的非终结符为左部的各产生式的右部,分为下面几种情况:
A、若遇到终结符,将该终结符加入左部非终结符的first集,继续扫描下一产生式;
B、若遇到符号“ε”,将“ε”加入左部非终结符的first集,继续扫描下一产生式;
C、若遇到非终结符,将该非终结符的 first集— {ε} 加入左部非终结符的first集,然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;若不为空,则继续扫描下一产生式;
D、若遇到“\0”,将“ε”加入左部非终结符的first集,继续扫描下一产生式;
E、重复ABCD等到first集的状态不再改变时,跳出循环

#include<bits/stdc++.h>
using namespace std;
int zjf(char c)
{
	if(c>='A'&&c<='Z')
	{
		return 0;
	}
	else if(c=='@')
	{
		return 0;
	}
	else if(c==','||c=='.'||c==':'||c=='?')
	{
		return 0;
	}
	else
	{
		return 1;
	}
}
int main()
{
	int biao;
	map<char,int>X;
	X['S']=1;
	X['A']=1;
	X['B']=1;
	X['C']=0;
	X['D']=0;
	int n;
	cout<<"输入文法产生式的个数(<=50):";
	cin>>n;
	string s[51];
	map<char,set<char> > first;
	cout<<"输入各产生式(每行一条,空用'@'表示):"<<endl;
	for(int i=0; i<n; i++)
	{
		cout<<"("<<i+1<<"):";
		cin>>s[i];
	}
	char t[51];
	int k=0;
	t[0]=s[0][0];
	for(int i=1; i<n; i++)
	{
		if(s[i][0]!=s[i-1][0])
		{
			t[++k]=s[i][0];
		}
	}
//	for(int i=0;i<=k;i++)
//		cout<<t[i]<<endl;
	int q;
	while(1)
	{
		int flag=0;
		for(int i=0; i<n; i++)
		{
			for(int j=3; j<s[i].size(); j++)
			{
				if(zjf(s[i][j]))
				{
					q=first[s[i][0]].size();
					first[s[i][0]].insert(s[i][j]);
					if(q!=first[s[i][0]].size())
						flag=1;
					break;
				}
				if(s[i][j]=='@')
				{
					q=first[s[i][0]].size();
					first[s[i][0]].insert('*');
					if(q!=first[s[i][0]].size())
						flag=1;
					break;
				}
				if(zjf(s[i][j])==0)
				{
					q=first[s[i][0]].size();
					set<char>::iterator its;
					for(its = first[s[i][j]].begin(); its!=first[s[i][j]].end(); its++)
					{
						if(*its!='*')
							first[s[i][0]].insert(*its);
					}
					if(q!=first[s[i][0]].size())
						flag=1;
					if(X[s[i][j]]==1)
					{
						biao=j;
					}
					else
					{
						break;
					}
				}
				if(biao==s[i].size()-1)
				{
					q=first[s[i][0]].size();
					first[s[i][0]].insert('*');
					if(q!=first[s[i][0]].size())
						flag=1;
					break;
				}
			}
		}
		if(flag==0)
			break;
	}
	for(int i=0; i<=k; i++)
	{
		cout<<"First("<<t[i]<<")"<<" = { ";
		set<char>::iterator it;
		for(it = first[t[i]].begin(); it!=first[t[i]].end(); it++)
		{
			cout<<*it<<" ";
		}
		cout<<"}"<<endl;
	}
}

求某一非终结符的FOLLOW集
(1)在产生式右部找到该非终结符,扫面它后面的符号,分为下面几种情况:
A、若是终结符,则将该终结符加入该非终结符的folow集;
B、若是非终结符,将该非终结符的 first集— {ε} 加入该非终结符的folow集,然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;
C、若是“\0”,则将该产生式的左部非终结符的follow集加入它的follow集。
(2)在产生式的右部继续查找该非终结符,若找到,转(1)步。

#include<bits/stdc++.h>
using namespace std;
int zjf(char c)
{
	if(c>='A'&&c<='Z')
	{
		return 0;
	}
	else if(c=='@')
	{
		return 0;
	}
	else if(c==','||c=='.'||c==':'||c=='?')
	{
		return 0;
	}
	else
	{
		return 1;
	}
}
int main()
{
	int biaoji;
	map<char,int>X;
	X['S']=1;
	X['A']=1;
	X['B']=1;
	X['C']=0;
	X['D']=0;
	map<char,set<char> > first;
	first['S'].insert('b');
	first['S'].insert('a');
	first['S'].insert('*');
	first['A'].insert('b');
	first['A'].insert('*');
	first['B'].insert('a');
	first['B'].insert('*');
	first['C'].insert('b');
	first['C'].insert('a');
	first['C'].insert('c');
	first['D'].insert('a');
	first['D'].insert('c');
	int n;
	cout<<"输入文法产生式的个数(<=50):";
	cin>>n;
	string s[51];
	map<char,set<char> > follow;
	cout<<"输入各产生式(每行一条,空用'@'表示):"<<endl;
	for(int i=0; i<n; i++)
	{
		cout<<"("<<i+1<<"):";
		cin>>s[i];
	}
	char t[51];
	int k=0;
	t[0]=s[0][0];
	for(int i=1; i<n; i++)
	{
		if(s[i][0]!=s[i-1][0])
		{
			t[++k]=s[i][0];
		}
	}
//	for(int i=0;i<=k;i++)
//		cout<<t[i]<<endl;
	follow['S'].insert('#');
	int m,q=3;
	while(q--)
	{
		int ff=0;
		for(int i=0; i<=k; i++)
		{
			for(int j=0; j<n; j++)
			{
				int flag=0;
				for(int k=3; k<s[j].size(); k++)
				{
					if(t[i]==s[j][k])
					{
						m=k+1;
						flag=1;
					}
				}
				if(flag==1)
				{
					if(m==s[j].size())
					{
						q=follow[t[i]].size();
						follow[t[i]].insert(follow[s[j][0]].begin(),follow[s[j][0]].end());
						if(q!=follow[t[i]].size())
							ff=1;
					}
					for(int k=m; k<s[j].size(); k++)
					{
						if(zjf(s[j][k]))
						{
							q=follow[t[i]].size();
							follow[t[i]].insert(s[j][k]);
							if(q!=follow[t[i]].size())
								ff=1;
						}
						if(!zjf(s[j][k]))
						{
							q=follow[t[i]].size();
							set<char>::iterator it;
							for(it = first[s[j][k]].begin(); it!=first[s[j][k]].end(); it++)
							{
								if(*it!='*')
									follow[t[i]].insert(*it);
							}
							if(q!=follow[t[i]].size())
								ff=1;
							if(X[s[j][k]])
							{
								biaoji=k;
							}
						}
						if(biaoji==s[j].size()-1)
						{
							q=follow[t[i]].size();
							follow[t[i]].insert(follow[s[j][0]].begin(),follow[s[j][0]].end());
							if(q!=follow[t[i]].size())
								ff=1;
						}
					}
				}
			}
		}
		if(ff==0)
			break;
	}
	for(int i=0; i<=k; i++)
	{
		cout<<"Follow("<<t[i]<<")"<<" = {";
		set<char>::iterator it;
		for(it = follow[t[i]].begin(); it!=follow[t[i]].end(); it++)
		{
			cout<<*it<<" ";
		}
		cout<<"}"<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/wl1780852311/article/details/90054485
今日推荐