C++实现first集follow集

C++实现first集follow集

“@”代替字符“ε”,“i”代替字符“id”

#include<iostream>
#include<vector>
#include<string>
#include<fstream>

using namespace std;

struct exp{
	char ter;	//终结符 
	bool e;	//是否能产生空转(用@表示)
	vector<string> nonter;	//非终结符 
};
vector<exp> v;	//产生式集合 

string T = "";	//非终结符集合 
string first[20];	//first集合 
string follow[20];	//follow集合 

//将文件中的文法转换成产生式 
void fun1(string str){
	exp e;
	e.ter = str[0];
	e.e=false;
	int i = 3;
	for(int k = i;k <str.length();k++){
		if(str[k] == '|'){
			e.nonter.push_back(str.substr(i,k-i));
			i = k + 1;
		} else if(str[k] == '@'){
			e.e = true;		//存在空转@ 
			i = k + 2;
			k++;
		}
	}
	if(i < str.length()){
		e.nonter.push_back(str.substr(i));
	}
	v.push_back(e);
	T = T + str[0];
}

//求first集
void fun2(int p,exp e){
	for(int k = 0;k < e.nonter.size();k++){
		if(e.e){
			first[p] += '@';
		}
		char str=e.nonter[k][0];
		//A->a...,则a属于first(A) 
		if((str >= 'a'&&str <= 'z')||(str>='('&&str<='+')){
			first[p] += str;
		}//A->B...,则first(A)+=first(B) 
		else if((str >= 'A'&&str <= 'Z')&&str!=e.ter){
			int j = T.find(str);
			fun2(p,v[j]);	
		}
	}
}

//求follow集 
void fun3(int n,char a){
	//开始非终结符follow集包含'$' 
	if(a==T[0])
		follow[n]+="$";
	for(int i = 0;i < T.length();i++){
		for(int k = 0;k < v[i].nonter.size();k++){
			if(v[i].nonter[k].find(a) != string::npos){
				int loc = v[i].nonter[k].find(a);
				//B->...A,则follow(A)+=follow(B) 
				if((loc == v[i].nonter[k].length()-1)&&a!=v[i].ter){
					//S->...A,则follow(A)+='$' 
					if(i==0) follow[n] += "$";
					fun3(n,T[i]);
				} else if(loc < v[i].nonter[k].length()-1){
					char loc1 = v[i].nonter[k][loc+1];
					//...->...Aa...,则follow(A)+='a' 
					if((loc1 >= 'a' && loc1 <= 'z')||(loc1>='('&&loc1<='+')){
						follow[n] += loc1;
					} else{
						int m = 0;
						//...->...AB...,则follow(A)+=(first(B)-'@') 
						for(;m < T.length();m++){
							if(T[m] == loc1){
								follow[n] += first[m];
								break;
							}
						}
					}	
				}
			}
		}
	}
}
//将空转符去掉,添加新的产生式 
void fun4(){
	for(int i=0;i<v.size();i++){
		if(v[i].e){
			for(int j=0;j<v.size();j++){
				for(int k=0;k<v[j].nonter.size();k++){
					int n=v[j].nonter[k].find(v[i].ter);
					string str=v[j].nonter[k];
					if(n>=0)
						v[j].nonter.push_back(str.substr(0,n)+str.substr(n+1));
				}
			}	
		}
	}	
}

void fun5(){
	for(int i = 0;i < v.size();i++){
		exp e = v[i];
		//打印整理后的文法 
		for(int j=0;j<e.nonter.size();j++)
			cout<<e.ter<<"->"<<e.nonter[j]<<endl;
		if(e.e)
			cout<<e.ter<<"->"<<"@"<<endl;
		fun2(i,e);
		fun3(i,e.ter);
	}
}

int main(){
	ifstream open("D:\\课程资料\\编译原理\\1.txt");
	string str;
	if(!open.is_open())
		cout<<"open file failed"<<endl;
	while(getline(open,str)){
		fun1(str);
	}
	open.close();
	fun4();
	fun5();
	cout<<"first集如下:"<<endl;
	for(int len = 0;len < T.length();len++){
		str="";
		//去重
		for(int i=0;i<first[len].length();i++){
			char c = first[len][i];
			if(str.find(c)== string::npos)
				str+=c;
		}
		first[len]=str;
		cout<<T[len]<<": "<<first[len]<<endl;
	}
	cout<<"follow集如下:"<<endl;
	for(int len = 0;len < T.length();len++){
		str="";
		//去重和将@符去掉 
		for(int i=0;i<follow[len].length();i++){
			char c = follow[len][i];
			if((str.find(c)== string::npos)&&c!='@')
				str+=c;
		}
		follow[len]=str;
		cout<<T[len]<<": "<<follow[len]<<endl;
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述

参考链接: [https://blog.csdn.net/TKFEET/article/details/103000673]

  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值