编译原理实验报告.docx

上传人:b****2 文档编号:24242823 上传时间:2023-05-25 格式:DOCX 页数:31 大小:181.79KB
下载 相关 举报
编译原理实验报告.docx_第1页
第1页 / 共31页
编译原理实验报告.docx_第2页
第2页 / 共31页
编译原理实验报告.docx_第3页
第3页 / 共31页
编译原理实验报告.docx_第4页
第4页 / 共31页
编译原理实验报告.docx_第5页
第5页 / 共31页
点击查看更多>>
下载资源
资源描述

编译原理实验报告.docx

《编译原理实验报告.docx》由会员分享,可在线阅读,更多相关《编译原理实验报告.docx(31页珍藏版)》请在冰豆网上搜索。

编译原理实验报告.docx

编译原理实验报告

《编译原理》实验报告

专业班级:

计093班

学号:

姓名:

指导老师:

王森玉

 

实验内容:

1.求出每个非终结符的FIRST集合

2.求出每个产生式右部的FIRST集合

3.求出每个非终结符的Follow集合

实验环境:

VisualStudio2010

实验目的:

让同学们掌握FIRST集合和FOLLOW集合的求法

实验演示:

因为不知道怎么用电脑输出’ε’符号,我在代码里用’@’来表示‘ε’.以‘$’来结束输入

测试数据1:

S->aH

H->aMd|d

M->Ab|@

A->aM|e

输出结果:

测试数据2:

S->AB

S->bC

A->@

A->b

B->@

B->aD

C->AD

C->b

D->aS

D->c

输出结果:

测试数据3:

E->TX

X->+TX|@

T->FY

Y->*FY|@

F->i|(E)

输出结果:

容错处理:

由于出错情况比较多,我们随便测试一组错误。

测试数据:

S-ABA->@B->@

输出结果:

实验感想:

经过这几次的实验,不仅让我们更加深刻的知道了first集合和follow集合的计算步骤和方法,还很好的培养了我们动手能力。

虽然这两个集合用笔算的方法很简单,但是要让计算机来演算就不是那么容易了,这需要设计合理的数据结构和算法才能正确地求出结果。

当然在设计算法的时候难免会出现错误,这就需要我们这些程序员们仔细的去调试,发现错误并改正。

本以为这次的实验代码不会很长,但是实际写好了却有好几百行,可能是我的算法不够好吧。

总的来讲这次的实验没有遇到太大的问题,因为课上老师很认真的给我们讲解了它们的求法,笔推也做了好几次练习,让我们理清了思路。

 

实验代码:

#include

#include

#defineMAX50

charcss[MAX][MAX];//保存所有的产生式

intcount=0;

intcnt=0;

structL{//保存所有的终结符

charch;

intflag;//1:

能推出ε,0:

不能,初值:

-1

intnum;

charfirst[MAX];

ints;//first的长度

charfollow[MAX];

intl;//follow的长度

}l[MAX];

//对输入的格式进行控制,并校验输入是否符合格式

inthandle(chara[])

{

intlen,i=0,j,k;

len=strlen(a);

while(a[i]!

=10)

{

if(a[i]=='$')

return2;

if((''==a[i])||(9==a[i]))

{

i++;

continue;

}

if((a[i]>='A')&&(a[i]<='Z'))

{

if((a[i+1]!

='-')||(a[i+2]!

='>'))

{

printf("产生式格式错误\n");

return-1;

}

else

{

j=i;

k=0;

while((a[j]!

='')&&(a[j]!

=9)&&(a[j]!

='$')&&(a[j]!

=10))

{

if(a[j]=='|')

{

css[count][k]='\0';

count++;

if((a[j+1]=='')||(a[j]==9)||(a[j]=='$')||(a[j]==10))

{

printf("产生式格式错误\n");

return0;

}

css[count][0]=a[i];

css[count][1]=a[i+1];

css[count][2]=a[i+2];

k=3;

j++;

continue;

}

css[count][k]=a[j];

k++;

j++;

}

css[count][k]='\0';

i=j;

count++;

}

}

else

{

printf("产生式格式错误\n");

return-1;

}

}

return0;

}

//从键盘获得输入

intinput()

{

chara[MAX*MAX];

intv;

printf("输入产生式,产生式之间以空格回车或Tab键分隔,并以$键结束.\n");

printf("用@表示虚拟符号ε,终结符用大写字母表示,其他字符表示非终结符\n");

while

(1)

{

fgets(a,MAX*MAX,stdin);

v=handle(a);

if(v==-1)

return-1;

if(v==2)

return0;

}

}

//求出能推出ε的非终结符

voidseekEmpty()

{

inti,j,k,t;

intflag=0,flag2=0;

intlen,c;

chara[MAX][MAX],ch;

for(i=0;i

{

strcpy(a[i],css[i]);

}

//求出含有的非终结符的个数,并把各终结符保存起来

for(i=0;i

{

for(j=0;j

{

if(l[j].ch==a[i][0])

{

l[j].num++;

flag=1;

break;

}

else

flag=0;

}

if((!

cnt)||(!

flag))

{

l[cnt].ch=a[i][0];

l[cnt].flag=-1;

l[cnt].num=1;

l[cnt].s=0;

l[cnt].l=0;

cnt++;

flag=1;

continue;

}

}

c=count;

while(c)

{

for(i=0;i

{

//如果该终结符推出ε,从a[]中删除所有带有该终结符的产生式

if(a[i][3]=='@')

{

ch=a[i][0];

for(j=0;j

{

if(ch==a[j][0])

{

if(j!

=c-1)

{

for(k=j;k

strcpy(a[k],a[k+1]);

c--;

j--;

}

else

{

c--;

j--;

}

}

}

for(j=0;j

{

if(ch==l[j].ch)

{

l[j].flag=1;

break;

}

}

i--;

continue;

}

len=strlen(a[i]);

for(j=3;j

{

//当该产生式右边含有非终结符时从a[]中删除该条记录

if((a[i][j]<'A')||(a[i][j]>'Z'))

{

flag2=1;

break;

}

}

if(flag2)

{

for(k=0;k

{

if(a[i][0]==l[k].ch)

{

l[k].num--;

if(l[k].num==0)

l[k].flag=0;

break;

}

}

if(i!

=c-1)

for(k=i;k

{

strcpy(a[k],a[k+1]);

}

c--;

i--;

flag2=0;

continue;

}

//如果产生式右边为非终结符看看该终结符能不能推出ε

for(j=3;j

{

if((a[i][j]>='A')&&(a[i][j]<='Z'))

{

for(k=0;k

{

if(a[i][j]==l[k].ch)

{

if(l[k].flag==0)

{

flag2=1;

break;

}

elseif(l[k].flag==1)

{

for(t=j;t

a[i][t]=a[i][t+1];

a[i][len-1]='\0';

j--;

len--;

break;

}

break;

}

}

if(flag2)

break;

}

}

if(a[i][3]=='\0')

{

ch=a[i][0];

for(j=0;j

{

if(ch==a[j][0])

{

if(j!

=c-1)

{

for(k=j;k

strcpy(a[k],a[k+1]);

c--;

j--;

}

else

{

c--;

j--;

}

}

}

i--;

for(k=0;k

{

if(ch==l[k].ch)

{

l[k].flag=1;

break;

}

}

}

if(flag2)

{

for(k=0;k

{

if(a[i][0]==l[k].ch)

{

l[k].num--;

if(l[k].num==0)

l[k].flag=0;

}

}

if(i!

=c-1)

for(k=i;k

{

strcpy(a[k],a[k+1]);

}

c--;

i--;

flag2=0;

continue;

}

}

}

}

//求每个非终结符的First集合

voidseekFirstVn()

{

inti,j,k,t,t1,t2,c,item;

intlen,s,flag=0,flag2=0,fchange;

chara[MAX][MAX],ch[MAX];

for(i=0;i

{

strcpy(a[i],css[i]);

}

c=count;

while

(1)

{

fchange=0;

for(i=0;i

{

//右部为ε,将ε并入到左部的First中

if(a[i][3]=='@')

{

/*for(j=0;j

{

if(l[j].ch==a[i][0])

{

for(k=0;k

if(l[j].first[k]==a[i][3])

{

flag=1;

break;

}

if(!

flag)

{

l[j].first[l[j].s]=a[i][3];

l[j].s++;

l[j].first[l[j].s]='\0';

fchange=1;

break;

}

flag=0;

}

}*/

//从当前列表a[]中删除

if(i!

=c-1)

for(j=i;j

strcpy(a[j],a[j+1]);

c--;

i--;

continue;

}

len=strlen(a[i]);

//产生式右边符号为终结符时,将该终结符并入到左部的First集合中

for(j=3;j

{

if((a[i][j]<'A')||(a[i][j]>'Z'))

{

for(k=0;k

{

if(a[i][0]==l[k].ch)

{

for(t=0;t

{

if(a[i][j]==l[k].first[t])

{

flag=1;

break;

}

}

if(!

flag)

{

l[k].first[l[k].s]=a[i][j];

l[k].s++;

l[k].first[l[k].s]='\0';

fchange=1;

}

flag=0;

break;

}

}

//从a[][]中删除该条产生式

if(i!

=c-1)

for(k=i;k

strcpy(a[k],a[k+1]);

c--;

i--;

break;

}

//产生式右边符号为非终结符时

elseif((a[i][j]>='A')&&(a[i][j]<='Z'))

{

/*将该非终结符的FIRST集合除去ε并入到当前

非终结符的FIRST集合中*/

for(k=0;k

{

if(a[i][j]==l[k].ch)

{

for(t=0;t

{

if(a[i][0]==l[t].ch)

{

for(t1=0;t1

{

for(t2=0;t2

{

if(l[k].first[t1]==l[t].first[t2])

{

break;

}

}

if((t2==l[t].s)&&(l[k].first[t1])!

='@')

{

fchange=1;

l[t].first[l[t].s]=l[k].first[t1];

l[t].s++;

l[t].first[l[t].s]='\0';

}

}

break;

}

}

break;

}

}

if(l[k].flag)

continue;

else

break;

}

}

}

if(!

fchange)

{

for(i=0;i

{

if(l[i].flag)

{

l[i].first[l[i].s]='@';

l[i].s++;

l[i].first[l[i].s]='\0';

}

printf("FIRST(%c):

%s\n",l[i].ch,l[i].first);

}

printf("\n");

break;

}

}

}

//求产生式右部的First集合

voidseekFirstRight()

{

structRight{

chara[MAX];

charfirst[MAX];

ints;

}r[MAX];

inti,j,k,t;

intcnt=0,len,len1,flag=0;

for(i=0;i

{

for(j=0;j

{

if(!

strcmp(css[i]+3,r[j].a))

{

flag=1;

break;

}

}

if(flag)

{

flag=0;

continue;

}

strcpy(r[j].a,css[i]+3);

r[j].s=0;

cnt++;

}

for(i=0;i

{

len=strlen(r[i].a);

for(j=0;j

{

//遇到终结符

if(r[i].a[j]=='@')

{

r[i].first[r[i].s]='@';

r[i].s++;

r[i].first[r[i].s]='\0';

break;

}

elseif((r[i].a[j]<'A')||(r[i].a[j]>'Z'))

{

r[i].first[r[i].s]=r[i].a[j];

r[i].s++;

r[i].first[r[i].s]='\0';

break;

}

else

{

for(k=0;k

{

if(r[i].a[j]==l[k].ch)

{

len1=strlen(l[k].first);

for(t=0;t

{

if(l[k].first[t]!

='@')

{

r[i].first[r[i].s]=l[k].first[t];

r[i].s++;

r[i].first[r[i].s]='\0';

}

}

break;

}

}

if(l[k].flag)

{

if(j==len-1)

{

r[i].first[r[i].s]='@';

r[i].s++;

r[i].first[r[i].s]='\0';

}

continue;

}

else

break;

}

}

}

for(i=0;i

{

printf("FIRST(%s):

%s\n",r[i].a,r[i].first);

}

printf("\n");

}

//求每个非终极符的Follow集合

voidseekFollow()

{

inti,j,k,t,t1,t2,t3,c=0;

intflag=0,len;

intfchange;//判断一次循环是否有改动的地方

chara[MAX][MAX],ch[MAX];

for(i=0;i

{

len=strlen(css[i]);

for(j=3;j

{

if((css[i][j]>='A')&&(css[i][j]<='Z'))

{

break;

}

}

if(j!

=len)

{

strcpy(a[c],css[i]);

c++;

}

}

l[0].follow[l[0].l]='#';

l[0].l++;

l[0].follow[l[0].l]='\0';

while

(1)

{

fchange=0;

for(i=0;i

{

len=strlen(a[i]);

for(j=3;j

{

if((a[i][j]>='A')&&(a[i][j]<='Z'))

{

//判断该非终结符的前一位是否为非终结符,是的话,

//将其First集合去ε后并到其前一位非终结符的Follow集合中

if((a[i][j-1]>='A')&&(a[i][j-1]<='Z'))

{

for(k=0;k

{

if(a[i][j-1]==l[k].ch)

{

for(t=0;t

{

if(a[i][j]==l[t].ch)

{

for(t1=0;t1

{

i

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 纺织轻工业

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1