⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cfgsimplified.cpp

📁 CFG上下文无关文法的化简程序
💻 CPP
字号:
// CFGSimplified.cpp : Defines the entry point for the console application.
//@author LiuHao ShenZhen University 刘浩 2008年11月1日

#include "stdafx.h"
#include "CFGSimplified.h"
#include <sstream>
#include   <stdio.h>   

void Simplify::InitParam(){//初始化,输入要化简的CFG
	int i=0;
	cout<<"请认真阅读完下面的说明后按提示操作"<<endl;
	cout<<"请输入非终结符号集N,每两个非终结符号间空一格,每两个字符都不能相等,全部输入完毕后再输入#回车"<<endl;
	cout<<"注意每个非终结符只能用一个字符表示,最好是大写的英文字母,可以输入最多10个字符"<<endl;
    while(true){
		cin>>N[++i];
		if (N[i]=='#'||i>=10) break;//输入#号表示输入完毕
			}
		NO_N=i;
       // cout<<"NO_N="<<NO_N<<endl;
 
		i=0;
		 fflush(stdin); //清除缓冲区
		cout<<"请输入终结符号集T,每两个终结符号间空一格,每两个字符都不能相等,全部输入完毕后再输入#回车"<<endl;
		cout<<"注意每个终结符只能用一个字符表示,最好是小写的英文字母和数字标点,且不能为#"<<endl;
		cout<<"可以输入最多10个字符"<<endl;
		while(true){
		cin>>T[++i];
		if (T[i]=='#'||i>=10) break;//输入#号表示输入完毕
			}
         NO_T=i;
	//	 cout<<"NO_T="<<NO_T<<endl;
		
		i=0;
			cout<<"请输入产生式集P,每输入完一个产生式回车,不要输入两个完全一样的产生式"<<endl;
		cout<<"注意产生式应当写成诸如S->AwB|BaV等合法的形式,→用->代替,若产生式已经输入完,则输入#回车"<<endl;
		cout<<"最多可以输入的产生式为20个"<<endl;
	    fflush(stdin); //清除缓冲区
		while(true){
	
		cout<<"请输入第"<<i+1<<"个产生式,每输入完一个产生式回车"<<endl;

		cin>>P[++i].value;
		//cout<<"子串"<<P[i].substr(1,2)<<endl;
		if(P[i].value.substr(1,2)!="->"&&P[i].value!="#"){
			cout<<"您输入的字符串不合法,请认真阅读上面的说明并重新输入!注意大小写"<<endl;
			i--;
									}
		if (P[i].value=="#"||i>=20)	break;//输入#号表示输入完毕
		}
        NO_P=i;
	//	 cout<<"NO_P="<<NO_P<<endl;

			
		fflush(stdin); //清除缓冲区
		cout<<"请输入开始符号集S回车"<<endl;
		cin>>S;

       int tmp=0;
		while(true){
			fflush(stdin); //清除缓冲区
		for(int j=1;j<=NO_N;j++){
			//cout<<"N["<<j<<"]="<<N[j]<<endl;
			if(N[j]==S) {
				tmp=1;	}     
								}
            if(tmp==1) break;
			cout<<"您输入的开始符号不在非终结符集里面,请检查后重新输入。注意大小写。"<<endl;
          
        	cout<<"请输入开始符号集S回车"<<endl;
			cin>>S;
		}
}
void Simplify::separate(){//将产生式中含'|'的通通分解,使最终的产生式不含'|'
	cout<<"下面为分解产生式,使之不含|的过程"<<endl;
	string str[20];
	int c=0;
	for(int m=1;m<=NO_P;m++){
		str[m]=P[m].value;}
	for(int m1=1;m1<=NO_P;m1++){
		if(str[m1].substr(0)=="#") break;
		while(true){
		int l=str[m1].find("|",3);
		if(l!=-1) 
		{P[++c].value=str[m1].substr(0,l);
		P[c].count=1;
		cout<<"产生式"<<P[c].value<<endl;
		str[m1].erase(3,l-2);}
		else
		{ P[++c].value=str[m1].substr(0);
		P[c].count=1;
			cout<<"产生式"<<P[c].value<<endl;
			break;}
		
		//cout<<"l="<<l<<endl;
		//cout<<"str="<<str[m1]<<endl;
		}//while
}//for m1
	NO_P=c;

	//更新产生式集P[NO_P]
		Produce str1[20];
		int c1=0;
		for(int q=1;q<=NO_P;q++){
			str1[q]=P[q];}
		for(int q1=1;q1<=NO_P;q1++){
		            
					P[++c1].flag=0;
					P[c1].value=str1[q1].value;
					P[c1].count=0;
		}//for q
			//	cout<<"P[1]="<<P[1].flag<<endl;
}

void Simplify::Step1(){//找出有用的非终结符

		cout<<"下面为找出有用的非终结符(即所有能直接或间接推出终结符串的非终结符)的过程"<<endl;
//	cout<<"NO_P="<<NO_P<<endl;
		int acount=0;//统计次数
	for(int i=1;i<=NO_P;i++){
	
		if (P[i].value=="#") break;
		for(int j=1;j<=NO_T;j++){//能直接推出终结符的有用,并加上标记
			stringstream ss;
			ss<<T[j];//将Char转换为string
			string s=ss.str();
			if(P[i].value.substr(3)==s&&s!="#") 
			{
				cout<<"产生式"<<P[i].value<<"有用"<<endl;
			P[i].flag=1;//标记为step1
			acount++;
			}
								}

	
							}


for(int t=1;t<=NO_P;t++){//所有有用产生式的个数不会超过产生式的个数,因此t不会超过NO_P
//cout<<"t="<<t<<endl;
	for(int n=1;n<=NO_P;n++){
				
				for(int k=1;k<=NO_P;k++){//能间接推出终结符的有用,加上标记
						 if(P[n].flag==1&&k!=i){
					if((P[k].value.find(P[n].value.substr(0,1),3)!=-1)&&P[k].count!=1) 
					{		cout<<"产生式"<<P[k].value<<"有用"<<endl;
							P[k].count=1;//已经加入了有用产生式的集合,不必第二次加入		
						P[k].flag=1;//标记为step1
						acount++;
						//cout<<P[k].value<<P[k].flag<<endl;
					}//if P[n] substr
														
			 }// if p[n] flag
	

			
										}//for k


						}//for n
}//for t

	//更新产生式集P[NO_P]
		Produce str2[20];
		
//	cout<<"NO_P="<<NO_P<<endl;
		for(int b=1;b<=NO_P;b++){
		str2[b]=P[b];
	
		//cout<<"str2["<<b<<"]="<<str2[b].value<<endl;
	//	cout<<"str2["<<b<<"]="<<str2[b].flag<<endl;
		}//for
		int b1=1;
		int c2=0;
	while(true){
			if(str2[b1].flag==1&&str2[b1].value.substr(3)!="#") {
					P[++c2].flag=str2[b1].flag;
					P[c2].value=str2[b1].value;
					P[c2].count=0;
						}
			b1++;
			if(b1>NO_P) break;
		}//while
	       NO_P=acount;
		//	cout<<"NO_P="<<NO_P<<endl;
	
        
}

void Simplify::Step2(){//找出有用符号
cout<<"下面为找出有用符号,删除开始符号无法到达的符号与产生式的过程"<<endl;
int bcount=0;//统计次数

	for(int i1=1;i1<=NO_P;i1++){
		if(P[i1].value.substr(3)=="#") break;
			P[i1].count=0;
			stringstream ss1;
			ss1<<S;//将Char转换为string
			string s1=ss1.str();
			//cout<<"s1="<<s<<endl;
			//开始符号能直接到达的有用
			//cout<<P[i1].value.substr(0,1)<<endl;
			if(P[i1].value.substr(0,1)==s1){ P[i1].flag=2;//标记为step2
														P[i1].count=1;
													cout<<"产生式"<<P[i1].value<<"有用"<<endl;
														bcount++;}
	}//for i1

for(int t1=1;t1<=NO_P;t1++){//所有有用产生式的个数不会超过产生式的个数,因此t1不会超过NO_P
	for(int j1=1;j1<=NO_P;j1++){//P[j]直接可达
		for(int k1=1;k1<=NO_P;k1++){
			for(int n1=1;n1<=NO_N;n1++){
				stringstream ss2;
				ss2<<N[n1];//将Char转换为string
				string s2=ss2.str();
					//开始符号能间接到达的有用
				if((P[j1].value.find(s2,3)!=-1)&&P[j1].flag==2&&P[j1].value.substr(3)!="#"){
					if(P[k1].value.substr(0,1)==s2&&P[k1].count==0&&k1!=j1){
										P[k1].flag=2;//标记为step2
										P[k1].count=1;
										cout<<"产生式"<<P[k1].value<<"有用"<<endl;
										bcount++;
					}//if  P[k1]
				}//if P[1j]
			}//for n1
		}//for k1
	}//for j1
}//for t1


	//更新产生式集P[NO_P]
		Produce str2[20];
		
//	cout<<"NO_P="<<NO_P<<endl;
		for(int b=1;b<=NO_P;b++){
		str2[b]=P[b];
	
		//cout<<"str2["<<b<<"]="<<str2[b].value<<endl;
	//	cout<<"str2["<<b<<"]="<<str2[b].flag<<endl;
		}//for
		int b1=1;
		int c2=0;
	while(true){
			if(str2[b1].flag==2&&str2[b1].value.substr(3)!="#") {
					P[++c2].flag=str2[b1].flag;
					P[c2].value=str2[b1].value;
					P[c2].count=0;
						}
			b1++;
			if(b1>NO_P) break;
		}//while
	       NO_P=bcount;
			//cout<<"NO_P="<<NO_P<<endl;

}
void Simplify::Step3(){//消除ε产生式
	cout<<"下面为消除ε产生式的过程,为便于输入用^代替ε"<<endl;
	cout<<"若出现小写的s,则加入了新的产生式,s为新的开始符号"<<endl;
	//找出所有能导出ε产生式的非终结符
	string str[30];
	int T=0;
	for(int i=1;i<=NO_P;i++){
		if(P[i].value.substr(3)=="#") break;
			P[i].count=0;
		if(P[i].value.substr(3)=="^"){
			P[i].count=1;
			stringstream sst;
				sst<<S;//将Char转换为string
				string st=sst.str();
			cout<<P[i].value.substr(0,1)<<"能推出ε"<<endl;
			if(P[i].value.substr(0,1)!=st) cout<<"应当删除"<<endl;
			str[++T]=P[i].value.substr(0,1);}
	}//for i

	for(int m=1;m<=NO_P;m++){
	for(int j=1;j<=NO_P;j++){
		if(P[j].value.substr(3)=="#") break;
	
			int tmp=0;
			for(int k=1;k<=T;k++){
					if(str[k]!=P[j].value.substr(0,1)){
					tmp++;
				}//if
			}
			
			if (tmp>=T) tmp=1;
			for(k=1;k<=T;k++){
					if(str[k]==P[j].value.substr(3)&&P[j].count!=1&&tmp==1){
					P[j].count=1;
						cout<<P[k].value.substr(0,1)<<"能推出ε"<<endl;
					str[++T]=P[k].value.substr(0,1);
				}//if
				
			}//for k
		

	}//for j
	}//for m

	//消去除初始符号推出的ε产生式
				int	T1=0;
			stringstream ss1;
			ss1<<S;//将Char转换为string
			string s1=ss1.str();//开始符号
	for(int n=1;n<=T;n++){
		if(str[n]!=s1){//非开始符号
			for(int v=1;v<=NO_P;v++){
				if(str[n]==P[v].value.substr(0,1)&&P[v].value.substr(3)!="^"){
					P[v].flag=3;
					cout<<"产生式"<<P[v].value<<"加入消除ε后的产生式"<<endl;
					T1++;}
			}//for v
		}//if str[n]!=
		else{//开始符号S推出ε,则引入新的开始符号s能推出S和ε

				for(int v1=1;v1<=NO_P;v1++){
				if(str[n]==P[v1].value.substr(0,1)&&P[v1].value.substr(3)!="^"){
					P[v1].flag=3;
					cout<<"产生式"<<P[v1].value<<"加入消除ε后的产生式"<<endl;
					T1++;}
			}//for v1
			N[++NO_N]='s';
			P[++NO_P].value ="s->^";
				P[NO_P].flag=3;
					T1++;
				cout<<"产生式"<<P[NO_P].value<<"加入消除ε后的产生式"<<endl;
			P[++NO_P].value="s->"+s1;
				P[NO_P].flag=3;
					T1++;
				cout<<"产生式"<<P[NO_P].value<<"加入消除ε后的产生式"<<endl;
		}//else
	}//for n

		//更新产生式集P[NO_P]
		Produce str2[20];
		
//	cout<<"NO_P="<<NO_P<<endl;
		for(int b=1;b<=NO_P;b++){
		str2[b]=P[b];
	
		//cout<<"str2["<<b<<"]="<<str2[b].value<<endl;
	//	cout<<"str2["<<b<<"]="<<str2[b].flag<<endl;
		}//for
		int b1=1;
		int c2=0;
	while(true){
			if(str2[b1].flag==3&&str2[b1].value.substr(3)!="#") {
					P[++c2].flag=str2[b1].flag;
					P[c2].value=str2[b1].value;
					P[c2].count=0;
						}
			b1++;
			if(b1>NO_P) break;
		}//while
	       NO_P=T1;
			//cout<<"NO_P="<<NO_P<<endl;
}

int main()
{
	Simplify sim;
     sim.InitParam();//初始化,输入要化简的CFG
	 sim.separate();//将产生式中含'|'的通通分解,使最终的产生式不含'|'
	 sim.Step1();//找出有用的非终结符
	 sim.Step2();//找出有用符号
	 sim.Step3();//消除ε产生式

	 cout<<"输出结束,回车将退出";
	 getchar();   //保存屏幕输出
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -