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

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

一、实验目的
1.熟悉LL(1)语法分析的基本原理,语法分析的过程,以及语法分析中要注意的一些问题。
2. 复习高级语言及线性表、栈、图等典型数据结构,进一步加强用高级语言来解决实际问题的能力。
二、实验内容
编程实现下面的功能:
输入一个上下文无关文法,按照教材5.2节算法,求出各个非终结符能否推出ε,存储并显示结果。

1.计算能推出空的非终结符。

原理部分摘自清华大学出版社出版的《编译原理》一书
第一步:求能推出#的非终结符

结果如下图:

是否=>#
S

T

N

推导步骤:
(1)初值:“未定”

(2)扫描:

①先删除右部有终结符(只要有就删除)的产生式,若某符号的产生式全部被删除光了,则定义“否”(这里S直接可以定义否)

这个时候产生式剩下:

T->SN

N->,SN

N->#

②若某产生式右部为#,则该非终结符标“是”,并删除该终结符相关的所有产生式; (这里N可以定义为“是”,并N在左部的所有产生式)

扫描二维码关注公众号,回复: 6187771 查看本文章

这个时候产生式剩下:

T->SN

(3)扫描右部的每一个符号

①右部“是”对应的非终结符都要被删除(在经历(2)中的扫描产生的“是”的非终结符,这里是指N ; 这里的删除值得是删除单个字符,),若这使得某个某个产生式右部为空,则该产生式左部的符号,可以直接标“是”,然后删除该符号的相关产生式

例子:

经历扫描前还剩下 T->SN

之后删除N

T->S

(4)扫描右部的每一个符号

同上,右部如果对应为“否”的符号,则删除整个产生式(注意:区别上面的(3)上面是先删除单个字符,这里是直接删除整个产生式),若这使得产生式左部相关符号的所有的产生式都被删除,则标记“否”

S标记为“否”,则删除T->S,这时,关于T的所有产生式都被删除,这时T被标记“否”

得下图(也就是上文的图标):

是否=>#
S

T

N

#include<bits/stdc++.h>
using namespace std;
/*
未知-1
非空1
空0
*/
/*
在1
不在0
*/
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 zj(string s)
{
	for(int i=0; i<s.size(); i++)
	{
		if(zjf(s[i]))
		{
			return 1;
		}
	}
	return 0;
}
string delchar(char c,string s)
{
	string str= "";
	for(int i=0;i<s.size();i++)
	{
		if(s[i]!=c)
			str+=s[i];
	}
	return str;
}
int main()
{
	int n;
	map<string,int>ma;
	set<char> se;
	cout<<"输入文法产生式的个数(<=50):";
	cin>>n;
	string s[51];
	cout<<"输入各产生式(每行一条,空用'@'表示):"<<endl;
	for(int i=0; i<n; i++)
	{
		cout<<"("<<i+1<<"):";
		cin>>s[i];
		ma[s[i]]=1;
		se.insert(s[i][0]);
	}
	set<char>::iterator it;
	int k=0;
	char a[51];
	for(it=se.begin(); it!=se.end(); it++) //使用迭代器进行遍历
	{
		a[k++]=*it;
	}
	map<char,int> m;
	for(int i=0; i<k; i++)
	{
		m[a[i]]=-1;
//    	cout<<m[a[i]]<<" ";
	}
	//(1)
	for(int i=0; i<k; i++)
	{
		int cnt=0,cnt1=0;
		for(int j=0; j<n; j++)
		{
			if(zj(s[j].substr(3)))
			{
				ma[s[j]]=0;
			}
			if(zj(s[j].substr(3))&&s[j][0]==a[i])
			{
				cnt++;
			}
			if(s[j][0]==a[i])
			{
				cnt1++;
			}
		}
		if(cnt1==cnt)
		{
			m[a[i]]=1;
		}
	}
	//(2)
	for(int i=0; i<n; i++)
	{
		if(ma[s[i]]==1)
		{
			if(s[i].substr(3)=="@")
			{
				m[s[i][0]]=0;
			}
		}
	}
	for(int i=0; i<n; i++)
	{
		if(m[s[i][0]]==0)
		{
			ma[s[i]]=0;
		}
	}
//	(3)
	while(1)
	{
		int flag=0;
		for(int i=0; i<n; i++)
		{
			if(ma[s[i]]==1)
			{
				char de[51];
				int kk=0;
				for(int j=3; j<s[i].size(); j++)
				{
					if(m[s[i][j]]==0)
					{
						de[kk++]=s[i][j];
					}
				}
				for(int w=0;w<kk;w++)
				{
					s[i]=s[i].substr(0,3)+delchar(de[w],s[i].substr(3));
					ma[s[i]]=1;
				}
//				cout<<s[i]<<endl;
				if(s[i].size()==3)
				{
					m[s[i][0]]=0;
					ma[s[i]]=0;
					flag=1;
				}
			}
		}
		for(int i=0; i<n; i++)
		{
			for(int j=3; j<s[i].size(); j++)
			{
				if(ma[s[i]]==1)
				{
					ma[s[i]]=0;
					int ff=0;
					for(int k=0; k<n; k++)
					{
						if(ma[s[k]]==1)
						{
							if(s[i][0]==s[k][0])
							{
								ff=1;
							}
						}
					}
					if(ff==0)
					{
						m[s[i][0]]=1;
						flag=1;
					}
				}
			}
		}
		if(flag==0)
			break;
	}
	for(int i=0; i<k; i++)
	{
		cout<<a[i]<<"-> "<<m[a[i]]<<endl;
	}
}
/*
S->a
S->^
S->(T)
T->SN
N->,SN
N->@
*/

猜你喜欢

转载自blog.csdn.net/wl1780852311/article/details/90054354