#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define PROJECT_SET_SIZE 20
#define PROJECT_ID_POS 0
#define GRAMMER_ID_POS 1
#define GRAMMER_START_CHAR_POS 5
#define BFCHAR_POS 2
#define AFCHAR_POS 3
#define PROJECT_LEN_POS 4
#define ID 10000
char st[20][30];
int r;
struct grammer
{
char **g;
char vt[127];
char vn[27];
char s;
int line;
};
typedef struct
{
int id;
char ch;
}SElemType;
struct gprjt
{
char **gp;
char s;
int line;
};
typedef struct prjset
{
int id;
struct prjset *next;
char prjt[PROJECT_SET_SIZE+1];
char pointafter[PROJECT_SET_SIZE+1];
struct prjset *actorgo[PROJECT_SET_SIZE];
char pointbefore;
}prjset,*pprjset;
struct head
{
prjset *I;
prjset *tail;
int size;
};
char DOT = '~';
grammer g;
gprjt project;
head root;
void Input();
int OpenFile(char *s);
void CreateProjectSet();
void Closure(prjset *prjset);
int go(int rk, prjset *prjset);
void PrintPojectSet();
int IsInSet(char *s, char ch);
void JoinSet(char *s, char ch);
void main()
{
for(;;){
r=1;
cout<<"请输入文法规则(以#作为结尾):"<<endl;
for(;;){
string z;
cin>>z;
int m=0;
int w=0;
for(;m
if(z[m]=='#'){w=1;break; }
st[r][m]=z[m];
}
st[r][m]='@';
r=r+1;
if(w==1) break;
}
st[0][0]=st[1][0];st[0][1]='-';st[0][2]='>';st[0][3]=st[1][0];st[0][4]='@';
int count;
int i;
int j;
count = r;
g.line=count;
g.g=(char **)malloc(sizeof(char *)*g.line);
for(i=0; i
{
g.g[i]=(char *)malloc(21);
g.g[i][0] = i;
g.g[i][1] = 0;
}
for(int x=0;x
{
j = 2;
for(int y=0;st[x][y]!='@';y++)
{
if(st[x][y]=='-' && st[x][y+1]=='>'){y=y+1;continue;}
else
{
char ch=st[x][y];
g.g[x][j] = ch;
g.g[x][1]++;
j++;
}
}
}
g.vn[0] = g.vt[0] = 0;
for(i=0; i
{
for(j=2; j<=g.g[i][1]+1; j++)
{
if(g.g[i][j]>='A' && g.g[i][j]<='Z')
JoinSet(g.vn, g.g[i][j]);
else
JoinSet(g.vt, g.g[i][j]);
}
}
g.s = g.vn[1];
count = 0;
for(i=0; i
count += g.g[i][1];
if((project.gp=(char **)malloc(sizeof(char *)*count)) == NULL)exit(1);
int k;
int pointpos;
int m;
int n;
k = 0;
for(i=0; i
{
pointpos = GRAMMER_START_CHAR_POS + 1;
for(j=0; j
{
if((project.gp[k]=(char *)malloc(6+g.g[i][1])) == NULL)exit(1);
project.gp[k][PROJECT_ID_POS] = k;
project.gp[k][GRAMMER_ID_POS] = i;
project.gp[k][PROJECT_LEN_POS] = g.g[i][1]+1;
project.gp[k][GRAMMER_START_CHAR_POS] = g.g[i][2];
n = 3;
for(m=GRAMMER_START_CHAR_POS+1; m
{
project.gp[k][m] = g.g[i][n];
n++;
}
project.gp[k][pointpos] = DOT;
for(m=pointpos+1; m<=project.gp[k][PROJECT_LEN_POS]+PROJECT_LEN_POS; m++)
{
project.gp[k][m] = g.g[i][n];
n++;
}
if(pointpos==project.gp[k][PROJECT_LEN_POS]+PROJECT_LEN_POS)
{
project.gp[k][AFCHAR_POS] = '\0';
}
else
{
project.gp[k][AFCHAR_POS] = project.gp[k][pointpos+1];
}
if(pointpos==GRAMMER_START_CHAR_POS+1)
{
project.gp[k][BFCHAR_POS] = '\0';
}
else
{
project.gp[k][BFCHAR_POS] = project.gp[k][pointpos-1];
}
pointpos++;
k++;
}
}
project.s = g.s;
project.line = k;
cout<<"输出拓广文法:"<<"\n";
for(i=0; i
{
cout<<'('<<i+1<<')';
for(j=2; j<=g.g[i][1]+1; j++)
{
if(j == 3)
cout<<"->";
cout<<g.g[i][j];
}
cout<<"\n";
}
cout<<"输出项目集:"<<"\n";
cout<<"--------------------------------------\n";
for(i=0; i
{
cout<<'('<<i+1<<')';
for(j=GRAMMER_START_CHAR_POS; j<=project.gp[i][PROJECT_LEN_POS]+PROJECT_LEN_POS; j++)
{
if(j==GRAMMER_START_CHAR_POS+1)
cout<<"->";
if(project.gp[i][j] == DOT)
cout<<"·";
else
cout<<project.gp[i][j];
}
cout<<"\n";
}
cout<<"--------------------------------------\n";
cout<<"\n";
CreateProjectSet();
PrintPojectSet();
for(;;)
{
pprjset p;
p=root.I;
cout<<"输入字符串,判断其是否为当前文法的活前缀:";
string u;cin>>u;
int v[100]={0};
int s=1;
int k=0;
for(int e=0;e
int t=0;
for(i=1;i<=p->pointafter[0]; i++)
{
if(p->pointafter[i]==u[e]) { v[s]=p->actorgo[i-1]->id-ID; s++; p=p->actorgo[i-1]; t=1; break;}
}
if(t==0) { k=1;break;}
}
if(k==0) {cout<<"该字符串为该文法的活前缀"<<"\n";
cout<<"其路径为:";
for(int j=0;j
{cout<<"I"<<v[j];
if(j!=s-1) cout<<"->";
}
cout<<"\n";
}
else cout<<"该字符串不是该文法的活前缀"<<"\n";
cout<<"继续输入字符串?(输入N停止输入,输入其他字符继续)";
char q;cin>>q;
if(q=='N') break;
}
}
}
void CreateProjectSet()
{
int i;
int j;
int k;
int id = ID;
pprjset p,q;
root.I = root.tail = NULL;
if((p = (pprjset)malloc(sizeof(prjset))) == NULL) exit(1);
p->id = id;
p->next = NULL;
p->prjt[0] = 0;
p->pointafter[0] = 0;
p->pointbefore = '\0';
for(j=0; j
p->actorgo[j] = NULL;
for(j=0; j
p->actorgo[j] = NULL;
root.I = p;
root.tail = p;
root.size = 1;
for(i=0; i
{
if(project.s == project.gp[i][GRAMMER_START_CHAR_POS] && DOT == project.gp[i][GRAMMER_START_CHAR_POS+1])
{
JoinSet(root.I->prjt, project.gp[i][PROJECT_ID_POS]);
JoinSet(root.I->pointafter, project.gp[i][AFCHAR_POS]);
break;
}
}
Closure(root.I);
int pos;
for(q=root.I; q!=NULL; q=q->next)
{
for(i=1; i<=q->pointafter[0]; i++)
{
pos = i;
pos--;
if((p = (pprjset)malloc(sizeof(prjset))) == NULL) exit(1);
p->next = NULL;
p->prjt[0] = 0;
p->pointafter[0] = 0;
p->pointbefore = q->pointafter[i];
for(j=0; j
p->actorgo[j] = NULL;
for(j=1; j<=q->prjt[0]; j++)
{
if(project.gp[q->prjt[j]][AFCHAR_POS] == p->pointbefore)
go(q->prjt[j], p);
}
Closure(p);
pprjset ptr;
int flag;
int flagsame;
flagsame = 1;
flag = 1;
for(ptr=root.I; ptr!=NULL; ptr=ptr->next)
{
flag = 1;
if(p->prjt[0] == ptr->prjt[0])
{
for(k=1; k<=p->prjt[0]; k++)
{
if(!IsInSet(ptr->prjt, p->prjt[k]))
{
flag = 0;
break;
}//if
}//for
}//if
else
{
flag = 0;
}//else
if(flag == 0)
flagsame = 0;
else
{
flagsame = 1;
break;
}
}//for
if(flagsame)//flagsame == 1 , 有与*p相同的项目集,删除*p
{
q->actorgo[i-1] = ptr;
free(p);
}
else//将p挂到root.tail
{
q->actorgo[i-1] = p;
p->id = ++id;
root.tail->next = p;
root.tail = p;
root.size++;
}
}//for
}//for
}//CreateProjectSet
void Closure(prjset *pset)
{//rk 为项目的编号,prjset指向项目集
int i;
int j;
int rk;
for(i=1; i<=pset->prjt[0]; i++)
{
rk = pset->prjt[i];
if(IsInSet(g.vn, project.gp[rk][AFCHAR_POS]))//若圆点后字符为vn
{
for(j=0; j
{
if(project.gp[j][GRAMMER_START_CHAR_POS] == project.gp[rk][AFCHAR_POS] && project.gp[j][GRAMMER_START_CHAR_POS+1] == DOT)
{
JoinSet(pset->prjt, project.gp[j][PROJECT_ID_POS]);
JoinSet(pset->pointafter, project.gp[j][AFCHAR_POS]);
}//if
}//for
}//if
}//for
}//Closure
int go(int rk, pprjset prjset)
{//rk为项目编号,将rk的去向加入prjset指向的项目集中,返回项目编号,若无,返回-1
int i;
int j;
int rksize;
char rkS;
char rkpointafter;
if((rkpointafter = project.gp[rk][AFCHAR_POS]) == '\0')
{
return -1;
}
int pointpos;
pointpos = IsInSet(&project.gp[rk][PROJECT_LEN_POS], DOT);
pointpos += PROJECT_LEN_POS;
rksize = project.gp[rk][PROJECT_LEN_POS];
rkS = project.gp[rk][GRAMMER_START_CHAR_POS];
for(i=0; i
{
if(project.gp[i][GRAMMER_START_CHAR_POS] == rkS && project.gp[i][PROJECT_LEN_POS] == rksize && project.gp[i][BFCHAR_POS] == rkpointafter)
{
int flag;
flag = 1;
for(j=pointpos+2; j<=project.gp[i][PROJECT_LEN_POS]+PROJECT_LEN_POS; j++)
{
if(project.gp[i][j] != project.gp[rk][j])
{
flag = 0;
break;
}
}//for
if(flag)
{
JoinSet(prjset->prjt, project.gp[i][PROJECT_ID_POS]);//将项目加入项目集
if(project.gp[i][AFCHAR_POS] != '\0')
{JoinSet(prjset->pointafter, project.gp[i][AFCHAR_POS]);}//将项目圆点后的字符加入
return project.gp[i][PROJECT_ID_POS];
}//if
else
return -1;
}//if
}//for
}//go
void PrintPojectSet()
{
pprjset p;
int rk;
int i;
int j;
cout<<"输出识别活前缀的DFA\n";
for(p=root.I; p!=NULL; p=p->next)
{
cout<<"---------------------\n";
cout<<'I'<<p->id-ID<<"\n";
for(j=1; j<=p->prjt[0]; j++)
{
rk = p->prjt[j];
for(i=GRAMMER_START_CHAR_POS; i<=project.gp[rk][PROJECT_LEN_POS]+PROJECT_LEN_POS; i++)
{
if(i==GRAMMER_START_CHAR_POS+1)
cout<<"->";
if(project.gp[rk][i] == DOT)
cout<<"·";
else
cout<<project.gp[rk][i];
}//for
cout<<"\n";
}//for
cout<<"\n";
for(i=1; i<=p->pointafter[0]; i++)
{
cout<<"出度:"<<p->pointafter[i]<<"指向->"<<"I"<<p->actorgo[i-1]->id-ID<<"\n";
}//for
}//for
cout<<"---------------------\n";
}//PrintPojectSet
int IsInSet(char *s, char ch)
{
int i;
for(i=1; i<=s[0]; i++)
{
if(s[i] == ch) return i;
}
return 0;
}
void JoinSet(char *s, char ch)
{
int i;
if(!IsInSet(s,ch))
{
s[0]++;
i = s[0];
s[i] = ch;
}
}