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]