1.“@”代替字符“ε”
2.同一非终结符如有多条产生式必须写成一行,中间用“|”分隔,不允许有空格
代码存在很多问题,大量“非正常”情况都未考虑,谨慎参考
#include<iostream>
#include<vector>
#include<string>
#include<fstream>
using namespace std;
struct exp{
char ter; //终结符
bool e = false; //是否能产生空转(用@表示)
vector<string> nonter; //非终结符
};
vector<exp> v; //产生式集合
string T = ""; //终结符集合
string first[20]; //所有非终结符的first集
string f =""; //follow集
//将文件中的文法转换成产生式
void fun1(string str){
exp e;
e.ter = str[0];
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 fun3(int p,exp e,int index){
for(int k = 0;k < e.nonter.size();k++){
for(int i = index;i < e.nonter[k].length();i++){
if(e.nonter[k][i] >= 'a'&&e.nonter[k][i] <= 'z'){
first[p] += e.nonter[k][i];
break;
} else if(e.nonter[k][i] >= 'A'&&e.nonter[k][i] <= 'Z'){
int j = T.find(e.nonter[k][i]);
if(v[j].e){
fun3(p,v[j],0);
first[p] += '@';
}else{
fun3(p,v[j],0);
break;
}
}
}
}
}
void fun2(){
for(int i = 0;i < v.size();i++){
exp e = v[i];
fun3(i,e,0);
}
}
//求follow集
void follow(char a){
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 j = v[i].nonter[k].find(a);
if(j == v[i].nonter[k].length()-1){
follow(T[i]);
} else if(j < v[i].nonter[k].length()-1){
char p = v[i].nonter[k][j+1];
if(p >= 'a' && p <= 'z'){
f += p;
} else{
int m = 0;
for(;m < T.length();m++){
if(T[m] == p){
f = first[m];
}
}
if(first[m].find('@') != string::npos){
follow(T[i]);
}
}
}
}
}
}
}
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();
fun2();
cout<<"first集如下:"<<endl;
for(int len = 0;len < T.length();len++){
if(v[len].e){
first[len] += '@';
}
cout<<T[len]<<": "<<first[len]<<endl;
}
cout<<"输入非终结符:"<<endl;
char a;
cin>>a;
follow(a);
if(T.find(a) != string::npos){
f += '$';
}
string::iterator it;
//除去@,因为follow集中不能有@(空转)
for (it = f.begin(); it < f.end(); it++)
{
if (*it == '@')
{
str.erase(it);
it--;
}
}
cout<<a<<"的follow集:"<<f<<endl;
return 0;
}


本文介绍了一个用于文法分析的程序,该程序能够读取文法定义,计算并输出终结符的First集及指定非终结符的Follow集。通过解析文法文件,程序构建了文法的结构,进而计算出First集和Follow集,帮助理解文法的结构特性。
1004

被折叠的 条评论
为什么被折叠?



