编译原理实验报告.docx
《编译原理实验报告.docx》由会员分享,可在线阅读,更多相关《编译原理实验报告.docx(30页珍藏版)》请在冰豆网上搜索。
编译原理实验报告
武汉科技大学
计算机科学与技术学院
编译方法实验报告
学号:
2010113137071
姓名:
尹绮莉
班级:
计算机1003
指导老师:
邱谊敏
实验一词法分析器设计
2012-4-17
【实验目的】
1.熟悉词法分析的基本原理,词法分析的过程以及词法分析中要注意的问题。
2.复习高级语言,进一步加强用高级语言来解决实际问题的能力。
3.通过完成词法分析程序,了解词法分析的过程。
【实验内容】
用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。
调用Init初始化
从文件中读取一个非空白字符ch
N
判断ch
N
YY
Y
将值传入相应组中
Default
//对关键字等实现初始化
voidinit()
{inti;
for(i=0;i<=255;i++){ssym[i]=nul;}
ssym['+']=plus;ssym['-']=minus;ssym['*']=times;ssym['/']=slash;
ssym['(']=lparen;ssym[')']=rparen;ssym['=']=eql;ssym[',']=comma;
ssym['.']=period;ssym['#']=neq;ssym[';']=semicolon;
strcpy(&(word[0][0]),"begin");strcpy(&(word[1][0]),"call");
strcpy(&(word[2][0]),"const");strcpy(&(word[3][0]),"do");
strcpy(&(word[4][0]),"end");strcpy(&(word[5][0]),"if");
strcpy(&(word[6][0]),"odd");strcpy(&(word[7][0]),"procedure");
strcpy(&(word[8][0]),"read");strcpy(&(word[9][0]),"program");
strcpy(&(word[10][0]),"var");strcpy(&(word[11][0]),"while");
strcpy(&(word[12][0]),"write");strcpy(&(word[13][0]),"then");
wsym[0]=beginsym;wsym[1]=callsym;wsym[2]=constsym;
wsym[3]=dosym;wsym[4]=endsym;wsym[5]=ifsym;
wsym[6]=oddsym;wsym[7]=procsym;wsym[8]=readsym;
wsym[9]=programsym;wsym[10]=varsym;wsym[11]=whilesym;
wsym[12]=writesym;wsym[13]=thensym;
}
//读取源文件并判断单词类别
intKey(char*word)
{
for(inti=0;iif(!
strcmp(KeyWords[i],word))
return1;
return0;
}//确定是否为关键字
intsign(charword)
{
for(inti=0;iif(ope[i]==word)
return1;
return0;
}//确定是否为运算符
inttap(charword)
{for(inti=0;iif(edgesign[i]==word)
return1;
return0;
}//确定是否为分隔符符
voidTakenwrite2(charword)//4为运算符,5为分隔符
{
if(sign(word))
{
printf("(4,\"%c\")\n",word);
}
if(tap(word))
{printf("(5,\"%c\")\n",word);
}
}
voidTakenwrite1(char*word,intLen)//3为字符或者数字,2为标识符,1为关键字
{inta;
if(Key(word))
printf("(1,\"%s\")\n",word);
else{
if(word[0]=='\''&&word[Len-1]=='\'')//字符常量
printf("(3,\"%s\")\n",word);
elseif((a=atoi(word)))//字符串转化为数字
printf("(3,\"%d\")\n",a);
else{
if(word[0]!
='\0')printf("(2,\"%s\")\n",word);
}
}
}
intTaken()
{FILE*fp;
chartemp[10],ch='1',temp1;
charfilename[20];
inti,j;
printf("请输入文件名");
scanf("%s",filename);
if((fp=fopen(filename,"r"))==NULL)
{
printf("文件打开失败");
return0
;}
while(ch!
=EOF){
j=0;
i=0;
ch=fgetc(fp);
while(!
tap(ch)&&!
sign(ch)&&ch!
=''&&ch!
='\n'&&ch!
=EOF)
{temp[i]=ch;
temp[i+1]='\0';
ch=fgetc(fp);
i++;
}
Takenwrite1(temp,i);
temp[0]='\0';//清除字串
temp1=ch;
Takenwrite2(temp1);
temp1='\0';//清除字符
}
fclose(fp);
return1;
}
运行结果
实验二LL
(1)语法分析程序设计
2012-4-24
【实验目的】
1.熟悉判断LL
(1)文法的方法及对某一输入串的分析过程。
2.学会构造表达式文法的预测分析表。
【实验内容】
编写一个语法分析程序,对于给定的输入串,能够判断识别该串是否为给定文法的句型。
【实验部分代码】
structpRNode/*产生式右部结构*/
{
intrCursor;/*右部序号*/
structpRNode*next;
};
structpNode/*产生式结点结构*/
{
intlCursor;/*左部符号序号*/
intrLength;/*右部长度*/
/*注当rLength=1时,rCursor=-1为空产生式*/
structpRNode*rHead;/*右部结点头指针*/
};
structcollectNode/*集合元素结点结构*/
{
intnVt;/*在终结符集中的下标*/structcollectNode*next;
};
/*返回Vn在Vn表中的位置+100、Vt在Vt表中的位置,-1表示未找到*/
intIndexCh(charch)
{
intn;n=0;
while(ch!
=Vn[n]&&'\0'!
=Vn[n])n++;
if('\0'!
=Vn[n])return100+n;
n=0;
while(ch!
=Vt[n]&&'\0'!
=Vt[n])n++;
if('\0'!
=Vt[n])returnn;
return-1;
}
/*输出Vn或Vt的内容*/
voidShowChArray(char*collect)
{
intk=0;
while('\0'!
=collect[k])printf("%c",collect[k++]);
printf("\n");
}
Vn[n]='#';/*以"#"标志结束用于判断长度是否合法*/
k=n;/*k用于记录n以便改Vn[n]='\0'*/
if('#'!
=ch)
{
if('#'!
=(ch=getchar()))
{
while('#'!
=(ch=getchar()));printf("\n符号数目超过限制!
\n");
inErr=1;continue;
}
}
/*输入非终结符*/
/*输入终结符*/
voidInputVt()
{
intinErr=1;intn,k;charch;
while(inErr)
{
printf("\n请输入所有的终结符,注意:
");
printf("以#号结束:
\n");ch='';n=0;
/*初始化数组*/
while(nwhile(('#'!
=ch)&&(n{
if(''!
=ch&&'\n'!
=ch&&-1==IndexCh(ch))
{
Vt[n++]=ch;vtNum++;
}
ch=getchar();
}
Vt[n]='#';/*以"#"标志结束*/
k=n;/*k用于记录n以便改Vt[n]='\0'*/
if('#'!
=ch){
if('#'!
=(ch=getchar()))
{
while('#'!
=(ch=getchar()))
printf("\n符号数目超过限制!
\n");inErr=1;
continue;
}
}
/*正确性确认,正确则,执行下下面,否则重新输入*/
Vt[k]='\0';ShowChArray(Vt);ch='';
while('y'!
=ch&&'n'!
=ch)
{
if('\n'!
=ch)
{
printf("输入正确确认?
(y/n):
");
}
scanf("%c",&ch);
}
if('n'==ch){
printf("录入错误重新输入!
\n");inErr=1;
}
else
{inErr=0;
}}}
/*产生式输入*/
voidInputP()
{
charch;inti=0,n,num;
printf("请输入文法产生式的个数:
");
scanf("%d",&num);PNum=num;
getchar();/*消除回车符*/
printf("\n请输入文法的%d个产生式,并以回车分隔每个产生式:
",num);
printf("\n");
while(i{
printf("第%d个:
",i);
/*初始化*/
for(n=0;nbuffer[n]='\0';
/*输入产生式串*/
ch='';n=0;
while('\n'!
=(ch=getchar())&&n{
if(''!
=ch)buffer[n++]=ch;
}
buffer[n]='\0';
if(CheckP(buffer))
{
/*填写入产生式结构体*/
pRNode*pt,*qt;
P[i].lCursor=IndexCh(buffer[0]);
pt=(pRNode*)malloc(sizeof(pRNode));
pt->rCursor=IndexCh(buffer[3]);
pt->next=NULL;P[i].rHead=pt;n=4;
while('\0'!
=buffer[n])
{
qt=(pRNode*)malloc(sizeof(pRNode));
qt->rCursor=IndexCh(buffer[n]);
qt->next=NULL;pt->next=qt;pt=qt;n++;
}
P[i].rLength=n-3;i++;
/*调试时使用*/
}
else
printf("输入符号含非法在成分,请重新输入!
\n");
}
}
/*判断产生式正确性*/
boolCheckP(char*st)
{
intn;
if(100>IndexCh(st[0]))returnfalse;
if('-'!
=st[1])returnfalse;if('>'!
=st[2])returnfalse;
for(n=3;'\0'!
=st[n];n++)
{
if(-1==IndexCh(st[n]))returnfalse;
}
returntrue;
}
/*====================first&follow======================*/
/*计算first集,U->xx...*/
voidFirst(intU)
{inti,j;
for(i=0;i{if(P[i].lCursor==U)
{structpRNode*pt;pt=P[i].rHead;j=0;
while(j
{if(100>pt->rCursor)
{
/*注:
此处因编程出错,使空产生式时
rlength同样是1,故此处同样可处理空产生式*/
AddFirst(U,pt->rCursor);
break;
}
else
{
if(NULL==first[pt->rCursor-100])
{
First(pt->rCursor);
}
AddFirst(U,pt->rCursor);
if(!
HaveEmpty(pt->rCursor))
{
break;
}
else{
pt=pt->next;
}}
j++;
}
if(j>=P[i].rLength)/*当产生式右部都能推出空时*/AddFirst(U,-1);
}}}
/*加入first集*/
voidAddFirst(intU,intnCh)/*当数值小于100时nCh为Vt*/
/*当处理非终结符时,AddFirst不添加空项(-1)*/
{
structcollectNode*pt,*qt;intch;/*用于处理Vn*/pt=NULL;qt=NULL;
if(nCh<100)
{
pt=first[U-100];
while(NULL!
=pt)
{
if(pt->nVt==nCh)break;
else{
qt=pt;pt=pt->next;
}
}
if(NULL==pt)
{
pt=(structcollectNode*)malloc(sizeof(structcollectNode));
pt->nVt=nCh;pt->next=NULL;if(NULL==first[U-100])
{first[U-100]=pt;
}
else{
qt->next=pt;/*qt指向first集的最后一个元素*/
}
pt=pt->next;}
}
else{
pt=first[nCh-100];
while(NULL!
=pt)
{
ch=pt->nVt;if(-1!
=ch)
{
AddFirst(U,ch);
}
pt=pt->next;
}}}
/*判断first集中是否有空(-1)*/
boolHaveEmpty(intnVn)
{
if(nVn<100)/*为终结符时(含-1),在follow集中用到*/returnfalse;
structcollectNode*pt;pt=first[nVn-100];
while(NULL!
=pt)
{
if(-1==pt->nVt)returntrue;pt=pt->next;
}
returnfalse;
}
/*计算follow集,例:
U->xVy,U->xV.(注:
初始符必含#--"-1")*/
voidFollow(intV)
{
inti;structpRNode*pt;
if(100==V)/*当为初始符时*/AddFollow(V,-1,0);
for(i=0;i{pt=P[i].rHead;
while(NULL!
=pt&&pt->rCursor!
=V)pt=pt->next;
if(NULL!
=pt)
{
pt=pt->next;/*V右侧的符号*/
if(NULL==pt)/*当V后为空时V->xV,将左符的follow集并入V的follow集中*/
{if(NULL==follow[P[i].lCursor-100]&&P[i].lCursor!
=V)
{Follow(P[i].lCursor);
}
AddFollow(V,P[i].lCursor,0);
}
else/*不为空时V->xVy,(注意:
y->),调用AddFollow加入Vt或y的first集*/
{
while(NULL!
=pt&&HaveEmpty(pt->rCursor))
{
AddFollow(V,pt->rCursor,1);/*y的前缀中有空时,加如first集*/
pt=pt->next;
}
if(NULL==pt)/*当后面的字符可以推出空时*/
{if(NULL==follow[P[i].lCursor-100]&&P[i].lCursor!
=V)
{Follow(P[i].lCursor);
}AddFollow(V,P[i].lCursor,0);
}
else/*发现不为空的字符时*/
{
AddFollow(V,pt->rCursor,1);
}}}}}
/*当数值小于100时nCh为Vt*/
/*#用-1表示,kind用于区分是并入符号的first集,还是follow集
kind=0表加入follow集,kind=1加入first集*/
voidAddFollow(intV,intnCh,intkind)
{
structcollectNode*pt,*qt;intch;/*用于处理Vn*/pt=NULL;qt=NULL;
if(nCh<100)/*为终结符时*/
{
pt=follow[V-100];
while(NULL!
=pt)
{
if(pt->nVt==nCh)break;
else
{
qt=pt;pt=pt->next;
}
}
if(NULL==pt)
{
pt=(structcollectNode*)malloc(sizeof(structcollectNode));
pt->nVt=nCh;pt->next=NULL;
if(NULL==follow[V-100])
{
follow[V-100]=pt;
}
else{
qt->next=pt;/*qt指向follow集的最后一个元素*/
}
pt=pt->next;
}
}
else/*为非终结符时,要区分是加first还是follow*/
{
if(0==kind)
{
pt=follow[nCh-100];while(NULL!
=pt)
{
ch=pt->nVt;AddFollow(V,ch,0);pt=pt->next;}
}
else{
pt=first[nCh-100];
while(NULL!
=pt)
{
ch=pt->nVt;if(-1!
=ch)
{
AddFollow(V,ch,1);
}
pt=pt->next;
}}}}
/*输出first或follow集*/
voidShowCollect(structcollectNode**collect)
{
inti;structcollectNode*pt;i=0;
while(NULL!
=collect[i])
{
pt=collect[i];printf("\n%c:
\t",Vn[i]);
while(NULL!
=pt)
{
if(-1!
=pt->nVt)
printf("%c",Vt[pt->nVt]);
elseprintf("#");pt=pt->next;
}
i++;
}
printf("\n");
}
/*计算first和follow*/
voidFirstFollow()
{
inti;i=0;
while('\0'!
=Vn[i])
{
if(NULL==first[i])First(100+i);i++;
}
i=0;
while('\0'!
=Vn[i])
{
if(NULL==follow[i])Follow(100+i);
i++;
}
}
/*=================构造预测分析表,例:
U:
:
xyz===