编译原理LL(1)文法-判断,first,follow,select,分析字符串

编译原理LL(1)文法-判断,first,follow,select,分析字符串

好久不更新了,U盘格式化了,之前的代码都丢了,诶,好久了才想起来有个CSDN还没更新过,以后会坚持更新的,这次先挂上LLI文法吧,之后补上之前总结的算法,之后的内容大都是跟着课堂的,然后再根据自己跟大佬自学的东西,进行更新吧
——————————————————————————————————————————
这是实验要求:
编写程序,实现下列功能:

  1. 输入一个LL(1) 文法,存储
  2. 输出文法中每个非终结符的FIRST集和FOLLOW集
  3. 构造文法的预测分析表,并显示
  4. 输入一个符号串,可以输出该符号串的最左推导。
    ——————————————————————————————————————————
    这是判断文法能否推出空,first,follow,select的算法,通俗易懂,之后解释一下

——————————————————————————————————————————
1、判断各非汇总结符是否可以推出空
(1)将各非终结符出示状态置为“未知”
(2)按顺序扫描各产生式右部。分为下面几种情况:
a、若遇到符号“ε”,检查左部非终结符状态,若不是“空”,将其置为“空”,继续扫描下一产生式;
b、若遇到终结符,检查左部非终结符状态,若为“未知”,将其置为“非空”,继续扫描下一产生式;
c、若遇到非终结符,检查该非终结符状态,若为“未知”,则跳过当前产生式,扫描下一产生式;若为“非空”,检查左部非终结符状态,若为“未知”,将其置为“非空”,继续扫描下一产生式;
若为“空”,继续扫描本产生式的下一符号;
d、若遇到“\0”,检查左部非终结符状态,若不是“空”,将其置为“空”,继续扫描下一产生式;
e、若上述a,b,c,d过程引起了非终结符状态的改变,则跳到(2)处继续循环,否则跳出循环,判断结束。

2、求非终结符的first集
扫描以要求first集的非终结符为左部的各产生式的右部,分为下面几种情况:
A、若遇到终结符,将该终结符加入左部非终结符的first集,继续扫描下一产生式;
B、若遇到符号“ε”,将“ε”加入左部非终结符的first集,继续扫描下一产生式;
C、若遇到非终结符,将该非终结符的 first集— {ε} 加入左部非终结符的first集,然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;若不为空,则继续扫描下一产生式;
D、若遇到“\0”,将“ε”加入左部非终结符的first集,继续扫描下一产生式;

3、求某一非终结符的FOLLOW集
(1)在产生式右部找到该非终结符,扫面它后面的符号,分为下面几种情况:
A、若是终结符,则将该终结符加入该非终结符的folow集;
B、若是非终结符,将该非终结符的 first集— {ε} 加入该非终结符的folow集,然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;
C、若是“\0”,则将该产生式的左部非终结符的follow集加入它的follow集。
(2)在产生式的右部继续查找该非终结符,若找到,转(1)步。
4、求某产生式的select集
扫描产生式的右部,分为下面几种情况:
(1) 若是终结符,则将该终结符加入该产生式的select集;
(2) 若是“ε”,将左部非终结符的follow集加入该产生式的select集;
(3) 若是非终结符,将该非终结符的 first集— {ε} 加入该产生式的select集,然后检查该非终结符是否可以推出空,若可以为空,则扫描本产生式的下一符号;
(4) 若是“\0”,则将该产生式的左部非终结符的follow集加入该产生式的select集。
———————————————————————————————————————————
程序是用C++实现的,2维数组存储文法,这种简单的操作就不说了,first,follow,select,这些集合,都是要求不重复的,在程序实现的时候也是使用各种大循环来实现,所以,选择用set容器来存储这些集合,set有排序和去除重复的功能,具体的迭代器取值啥的,百度结合set的用法即可。

———————————————————————————————————————————
之后就是输入字符串,并进行分析,这时候我们先构造预测分析表,下面的程序按7即可,之后利用栈的思想,逐一分析,这里我用的是string字符串的用法,没用栈,栈取值比较麻烦,所以用的string,上代码吧
我的代码如果想执行8,必须先执行7!!!!!!!!
如果想再输入文法或者字符串的时候,请在运行一下,我懒得赋初值了。。。。。。
专业有大佬写了300,400行,用的map,map我也用不好,就数组吧,500多行。

#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef struct  
{
    char p[50][10];  
    int length;
}G;
typedef struct    
{
    char p1[20];     
	int length;      
}zhong1;
typedef struct    
{
    char p2[20];   
	int empty[20]; 
    int length;  
}fei1;
sets[50];
sets1[50];
sets2[50];
G g;
char biao[100];
zhong1 zhong;
fei1 fei;
int v[100];
void init();
void chushi();
void chuli();
void panduan();
void input();
char meau();
void first();
void follow();
void select();
void biaoo();
void chuanchuan();
int dian(char b);
void panduan_select();void chuanchuan();
string bb[100][100];
char meau()
{
	char ch;
    system("cls");
    printf("\n\n\n\n");
    printf("\t\tLL(1)语法分析演示程序\n");
    printf("\n\t  1.输入LL(1)文法\n");
    printf("\n\t  2.显示输入的LL(1)文法\n");
    printf("\n\t  3.判定非终结符是否为空\n");
    printf("\n\t  4.输出非终结符的First集\n");
    printf("\n\t  5.输出非终结符的Follow集\n");
    printf("\n\t  6.输出产生式的Sellect集\n\t");
    printf("\n\t  7.产生预测分析表\n\t");
    printf("\n\t  8.输入字符串并分析字符串\n\t");
    printf("\n\t  9.退出\n\t");
    printf("\n\t请输入你想要做的操作:");
	fflush(stdin);
	scanf("%c",&ch);
    return ch;
}
int feii(char c) 
{
   int i;
   for(i=0;i>g.length;
  cout<<"请输入产生式,空用@表示"<>g.p[i];
  }
  chuli();first();follow();select();
}
void chushi() 
{
	g.length=8;
	strcpy(g.p[0],"E->TX");
	strcpy(g.p[1],"X->+TX");
	strcpy(g.p[2],"X->@");
	strcpy(g.p[3],"T->FY");
	strcpy(g.p[4],"Y->*FY");
	strcpy(g.p[5],"Y->@");
	strcpy(g.p[6],"F->i");
	strcpy(g.p[7],"F->(E)");
	chuli();first();follow();select();
}
void chuli()
{
	int i,j,k;
	for(i=0;i='A'&&g.p[i][j]<='Z')
			{
				for(k=0;k'Z'||g.p[i][j]<'A')&&g.p[i][j]!='\0')
				{
					
					if(fei.empty[feii(g.p[i][0])]==-1)		
					{
						fei.empty[feii(g.p[i][0])]=0; 
						s=1;									
					}
					break;
				}
				else if(g.p[i][j]<='Z'&&g.p[i][j]>='A')
				{
				
					if(fei.empty[feii(g.p[i][j])]==-1)break;
					else if(fei.empty[feii(g.p[i][j])]==0)
					{ 
						if(fei.empty[feii(g.p[i][0])]==-1)		
						{
							fei.empty[feii(g.p[i][0])]=0; 
							s=1;	
						}
						break;
					}
				}
			}
				if(g.p[i][j]=='\0')
				{
					if(fei.empty[feii(g.p[i][0])]!=1)		
					{
						fei.empty[feii(g.p[i][0])]=1; 
						s=1;			
					}
				}
			}
				if(s==0)break;
	}
}
int dian(char b)
{
	int n;
	for(int k=0;k'Z'||g.p[i][j]<'A')&&g.p[i][j]!='\0')
			{
				s[dian(g.p[i][0])].insert(g.p[i][j]);break;
			}
			else if(g.p[i][j]<='Z'&&g.p[i][j]>='A')
			{
				m=dian(g.p[i][0]);n=dian(g.p[i][j]);
				set::iterator it1;
				for(it1=s[n].begin();it1!=s[n].end();it1++)
				{
					if(*it1!='@')
					s[m].insert(*it1);
				}
				if(fei.empty[n]==0)break;
				if(fei.empty[n]==1)continue;
			}
			if(g.p[i][j]=='\0')
			{
				s[dian(g.p[i][0])].insert('@');break;
			}
		}
	}
	}
}
void follow()
{
	s1[0].insert('#');
	int i,j,m,n,n1,d;
	for(int z=0;z='A')
			{
				for(d=j+1;d'Z'||g.p[i][d]<'A')&&g.p[i][d]!='\0')
					{
						s1[dian(g.p[i][j])].insert(g.p[i][d]);break;
					}
					else if(g.p[i][d]<='Z'&&g.p[i][d]>='A')
					{
						m=dian(g.p[i][j]);n=dian(g.p[i][d]);
						set::iterator it2;
						for(it2=s[n].begin();it2!=s[n].end();it2++)
						{
							if(*it2!='@')
							s1[m].insert(*it2);
						}
						if(fei.empty[n]==1)break;
					}
					else if(g.p[i][d]=='\0')
					{
						m=dian(g.p[i][j]);n=dian(g.p[i][0]);
						set::iterator it3;
						for(it3=s1[n].begin();it3!=s1[n].end();it3++)
						{
							s1[m].insert(*it3);
						}
					}
				}
			}
		}
	}
	}
}
void select()
{
	int i,j,w,n;
	for(i=0;i'Z'||g.p[i][j]<'A')&&g.p[i][j]!='\0'&&g.p[i][j]!='@')
			{
				s2[i].insert(g.p[i][j]);
				break;
			}
			else if(g.p[i][j]=='@'||g.p[i][j]=='\0')
			{
				n=dian(g.p[i][0]);
				set::iterator it5;
				for(it5=s1[n].begin();it5!=s1[n].end();it5++)
					s2[i].insert(*it5);
			}
			else if(g.p[i][j]<='Z'&&g.p[i][j]>='A')
			{
				n=dian(g.p[i][j]);
				set::iterator it6;
				for(it6=s[n].begin();it6!=s[n].end();it6++)
					{
						if(*it6!='@')
						s2[i].insert(*it6);
					}break;
			}
		}
	}
}
void panduan_select()
{
	int f=0,i,j;
	for(i=0;i ANS;
    			set_intersection(s2[i].begin(),s2[i].end(),s2[j].begin(),s2[j].end(),inserter(ANS,ANS.begin()));
				if(!ANS.empty()){
					f=1;
				}
			}
		}
	}
	if(f==1)cout<<"这不是LL(1)文法!!!\n\n";
	else 
	cout<<"这是LL(1)文法\n\n";
}
void biaoo()
{
	for(int i=0;i::iterator it6;
	for(int i=0;i>n1;
	int k1=1,i=0,f=0,ff=0;
	if(n1[n1.size()-1]!='#'){
		cout<<"请以#结尾"<0;i--)
		zuizuo1+=n[i];
		zuizuo3+=zuizuo2;
		zuizuo3+=zuizuo1;
		}
		if(n1[0]=='#')
		{
			int k4=zhongg('@');
			if(n[n.size()-1]=='#')
			{
			cout<<"接受\t"<';j--)n+=n2[j];zuizuo3+="->";continue;
			}
		}
		else
		{cout<<"分析出错!!!"<='1'&&ch<='9')
  {
    if(ch=='1')
	{	system("cls");
	cout<<"1是输入新文法,2是用初始定义的文法"<>cc;
    if(cc==1){
    	input();panduan();
	}
    else
    {chushi();
	panduan();
	}
	} 
    else if(ch=='2') 
	{
		system("cls");
		for(int k=0;k::iterator it;
		for(int i=0;i::iterator it4;
		for(int i=0;i::iterator it7;
		for(int i=0;i

——————————————
啊哈,有啥不懂的,评论问。
恰饭去了。。

你可能感兴趣的:(C语言基础编程,C++,编译原理,LL1文法,C语言,C++,编译原理,LL1文法)