编译实验报告.docx
《编译实验报告.docx》由会员分享,可在线阅读,更多相关《编译实验报告.docx(77页珍藏版)》请在冰豆网上搜索。
编译实验报告
二、课程设计正文
1.编写一个L-语言的词法分析器,从左到右逐个字符地对L-语言的源程序进行扫描,产生一个个单词符号的机内表示。
程序结构如图L-1所示:
scanner
IsAlpha
IsNumber
IsChar
Isother
OutPut
Error
图L-1
1.1Sanner()
1.功能:
完成初始化,并循环调用子模块,完成单词的识别。
2.算法描述如下
VoidScanner()
{调用ScannerInit()进行初始化;
读入源程序的第一个字符;
while(字符!
=EOF)
{if(字符==字母)IsAlPha();
elseif(字符==数字)IsNumber();
elseif(字符==‘’’)IsChar();
elseIsOther();
}
打印结束信息;
结束操作;
}
1.2IsAlPha()
1.功能:
识别保留字和标识符。
2.算法描述如下:
VoidIsAlPha()
{while(字符为字母或数字或’_’)
{记录当前字符;
读取下一字符;
}
判断当前字符串是否为保留字,并设置标志位h;
调用OutPut()函数输出保留字或标识符;
}
1.3IsNumber()
1.功能:
识别整数和实数。
2.算法描述如下:
voidIsNumber()
{
intflag=0;
while(字符为数字)
{记录当前字符;
读取下一字符;
If(字符为’.’号)
{记录当前字符;
flag=1;
读下一字符;
跳出循环;
}
}
记单词编码为整数的编码(当前Token为整数);
If(flag=1)
{if(当前字符为数字)
{记录当前数字;
while(当前字符为数字)
{记录字符;
读取下一字符;
}
记单词编码为实数的编码(当前Token为实数);
}
elseError
(2);
if(当前字符为’.’)删除余下数字;
}
if(当前字符为字母)舍去后面的部分;
OutPut();
}
1.4IsChar()
1.功能:
识别字符串。
2.算法描述:
voidIsChar()
{for(;;;)
{读取下一字符;
现行Token为字符串;
If(当前字符不是‘.’号)
记录字符;
Elsebreak;
}
OutPut();
读下一字符;
}
1.5IsOther()
1.功能:
识别其他单词。
2.算法描述如下:
voidIsOther()
{switch(当前字符)
{对于不同字符做出不同处理,主要有:
1、符号内容的记取;
2、查出机内码;
3、调用OutPut()输出至Token()文件;
4、读取下一字符;
5、对于错误符号将其删除,并报错;}
}
1.6ScannerInit()
1.功能:
进行初始化,主要包括:
1、建立单词编码表、token表、符号表,并将它们清空。
2、打开单词编码文件,并将单词编码读到编码表中。
1.7OutPut()
1.功能:
输出识别出的单词,包括:
2.若单词为标识符或常数再查,填符号表。
1.8Error()
1.功能:
判断错误原因。
2.在由词法分析程序对L语言源程序分析产生的token,符号表文件的基础上,从完成语法语义分析,并产生相应的中间代码-四元式序列。
2.1paser()
1.功能:
主模块,完成初始化,并调用复合语句分析模块和说明语句分析模块,完成分析任务。
2.算法描述如下:
voidpaser()
{初始化;
从Token文件读取第一个单词;
if(单词==program)
{读取下一单词;
if(单词==标识符)
{读取下一单词;
if(单词为‘;’)
{行数加一;
读取下一单词;
if(单词为var)
declear();
if(单词为begin)
{S_Begin();
if(code不是等于号)Error(49);
}
else出错处理;
}
else出错处理;
}
else出错处理;
}
else出错处理;
2.2S_Begin()
1.功能:
完成复合语句的分析。
2.算法描述
S_Begin()
{if(当前字符为begin)
{读取下一字符;
调用L_Analize();
if(当前字符为end)结束;
else非正常结束,返回0;
}
读取下一字符;
返回;
}
2.3L_Analize()
1.功能:
完成语句序列分析。
2.算法描述
L_Analize()
{intrtn;
switch(当前字符)
{caseIF:
调用S_IF()函数;break;
caseBEGIN:
调用S_Begin()函数;braek;
case标识符:
调用S_Let()函数;break;
caseWHILE:
调用S_While();break;
}
if(当前字符为‘:
’)
{行数加一;
读取下一字符;
递归调用L_Analize()
}
elsereturnrtn;
}
2.4S_Let()
1.功能:
完成赋值语句的分析。
2.算法分析
S_Let(inta)
{if(当前字符为标识符)
{if(需要记录变量的地址)记录赋值变量的地址;
读取下一个单词;
if(当前单词为赋值号)
{调用表达式分析函数L_Analize();
if(表达式正确)生成赋值句四元式;
}
}
else赋值句出错;
return四元式序号;
}
2.5S_IF()
1.功能:
完成条件语句的分析。
2.算法描述:
IntS_IF()
{inta;
intrtn=0;
定义一个真出口True_address和一个假出口Flase_address;
if(当前单词为if)
{布尔表达式初始化;
调用布尔表达式分析函数B_Analize();
rtn=布尔表达式的四元式首址;
产生无条件跳转四元式;
if(当前单词为then)
{读取下一单词;
switch(当前单词)
{caseIF:
调用S_IF()函数;break;
caseBEGIN:
调用S_Begin()函数;braek;
case标识符:
调用S_Let()函数;break;
caseWHILE:
调用S_While();break;
}
BackPatch();
if(当前单词为else)
{读取下一单词;
switch(当前单词)
{caseIF:
调用S_IF()函数;break;
caseBEGIN:
调用S_Begin()函数;braek;
case标识符:
调用S_Let()函数;break;
caseWHILE:
调用S_While();break;
}
BackPatch();
}
elsertn;
}
else报错;(缺少then)
}
rtn;
}
2.6S_While()
1.功能:
完成while循环语句的分析。
2.算法描述;
intS_While()
{intrtn=0;boor_value,True_address,False_address;
if(当前单词为while)
{rtn=布尔表达式分析函数B_Analize();
boor_value=布尔表达式值地址;
产生跳转四元式;
if(当前单词为do)
{读取下一单词;
switch(当前单词)
{caseIF:
调用S_IF()函数;break;
caseBEGIN:
调用S_Begin()函数;braek;
case标识符:
调用S_Let()函数;break;
caseWHILE:
调用S_While();break;
}
BackPatch();
BackPatch();
}
else出错,缺少do;
}
returnrtn;
}
2.7gen()
该函数形成一个四元式,并将其输出至四元式文件。
2.8E_Analize()
1.该函数是算术分析表达式的主模块,它调用算术表达式的子模块,采用递归下降分析法完成算术表达式的分析。
2.算术表达式的各个子模块:
a.E_Init()将算术表达式读入分析栈;
b.intE_AddSub()完成E->TE1|T的分析;
c.intE1_AddSub(inta)完成E1->+TE1|-TE1|^
d.T_MulDiv()完成T->FT1|F的分析;
e.T1_MulDiv(inta)完成T1->*FT1|/FT1|^;
f.F_Number()完成F->i|(E)的分析;
2.9B_Analize()
1.布尔表达式分析的主模块,调用其他布尔表达式的子模块,采用递归下降分析法完成布尔表达式的分析。
并返回该布尔表达式的首个四元式地址。
a.B_OR()完成B->LB|L的分析;
b.B1_OR(inta)完成B1->orLB1|^的分析;
c.L_AND()完成L->ML1|M的分析;
d.L1_AND()完成L1->andM1|^的分析;
e.M_NOT()完成M->notM|K的分析;
f.K_END()完成K->i|false|true|(B)的分析;
g.K_CMP()完成K->iSi,S-><>|=|<=|>=|>|<的分析。
三、课程设计总结
1、实验中遇到的问题
词法分析器程序中要读入一个单词编码文件,但是文件的格式在编写的时候和程序有点差异,因而导致输出结果再三的错误。
语法/语义分析器中,在修改符号表时,出现错误,最终没有的到正确结果。
2、对实验原理有更深的理解
通过该课程设计,掌握了什么是编译程序,编译程序工作的基本过程及其各阶段的基本任务,熟悉了编译程序总流程框图,了解了编译程序的生成过程,构造工具及其相关的技术对课本上的知识有了更深的理解,课本上的知识师机械的,表面的.通过把该算法的内容,算法的执行顺序在计算机上实现,把原来以为很深奥的书本知识变的更为简单,对实验原理有更深的理解。
3、对该理论在实践中的应用有深刻的理解
通过把该算法的内容,算法的执行顺序在计算机上实现,知道和理解了该理论在计算机中是怎样执行的,对该理论在实践中的应用有深刻的理解。
四、参考文献
[1]贺讯.编译方法学习指导与实践.北京:
机械工业出版社,第一版.2004年8月。
五、附录
1.单词编码文件ni.txt
and1
or11
begin2
program12
bool3
real13
+23
<=33
do4
then14
-24
<34
else5
true15
*25
<>35
end6
var16
/26
>36
false7
while17
.27
>=37
if8
标识符18
,28
integer9
整数19
:
29
not10
实数20
;30
(21
:
=31
)22
=32
char38
2.测试代码文件11.txt
programabc;
vara:
real;
begin
ifa<22.2thenx:
=c+d;
end
3.词法分析完整源代码
#include
#include
#include
#defineLENGTH61
#defineN100
/*********************************************************************/
typedefstructtoken
{
intlabel;
charname[30];
intcode;
intaddr;
}token;
typedefstructKeyWord
{
charname[30];
intcode;
}KeyWord;
typedefstructsymble
{
intnumber;
inttype;
charname[30];
}symble;
/*********************************************************************/
charch;
intvar_count;
interror_count;
intlabel_count;
intcode_count;
intaddr_count;
intLineOfPro;
charfilename[30];
FILE*KeyFin;
FILE*SourceFin;
FILE*TokenFout;
FILE*SymbleFout;
KeyWordkey[LENGTH];
tokenCurrentToken;
symbleCurrentSimble;
symbleSymbleList[N];
/*********************************************************************/
voidScanner();
voidScannerInit();
voidIsAlpha();
voidIsNumber();
voidIsAnotation();
voidIsChar();
voidIsOther();
voidOutPut();
voidError(inta);
intWordHave();
intstrcmp(char*s,char*t)
{
for(;*s==*t;s++,t++)
if(*s==0)return0;
return1;
}
/*********************************************************************/
intmain()
{
inti=0,j=0;
code_count=0;
LineOfPro=0;
var_count=0;
addr_count=1;
label_count=1;
for(i=0;i{
SymbleList[i].number=0;
SymbleList[i].type=0;
for(j=0;j<30;j++)SymbleList[i].name[j]='\0';
}
Scanner();
system("pause");
return0;
}
/************************主程序***************************************/
voidScanner()
{
inti=0;error_count=0;
ScannerInit();
printf("***************************************");
printf("*L语言词法分析器);
printf("***************************************");
printf("输入原文件名:
");
for(;;)
{
scanf("%c",&filename[i]);
if(filename[i]==10)
break;
i++;
}
filename[i]='\0';
if((SourceFin=fopen(filename,"rt"))==NULL)
{
printf("无法打开文件%s.\n",filename);
exit
(1);
}
if((TokenFout=fopen("token.txt","wt+"))==NULL)
{
printf("无法打开文件symble.txt\n");
exit
(1);
}
if((SymbleFout=fopen("symble.txt","wt+"))==NULL)
{
printf("无法打开文件symble.txt\n");
exit
(1);
}
ch=fgetc(SourceFin);
while(ch!
=EOF)
{
for(i=0;i<30;i++)CurrentToken.name[i]='\0';
if((ch>47)&&(ch<58))IsNumber();
else
{
if(((ch>64)&&(ch<90))||((ch>96)&&(ch<123))||(ch=='_'))IsAlpha();
else{if(ch=='\'')IsChar();
elseIsOther();
}
}
}
fclose(SourceFin);
fclose(TokenFout);
fclose(SymbleFout);
printf("分析完毕/\n");
}
/********************************初始化*******************************/
voidScannerInit()
{
inti=1;
intk=0;
if((KeyFin=fopen("ni.txt","rt"))==NULL)
{
printf("cannotopenni.txt\n");
exit
(1);
}
for(i=0;i<60;i++)
for(k=0;k<30;k++)key[i].name[k]='\0';
for(i=0;i<60;i++)
{
/*读入编码表*/
fscanf(KeyFin,"%s%d",key[i].name,&key[i].code);
}
fclose(KeyFin);
}
/*****************************数字处理********************************/
voidIsNumber()
{
intk=0;
intflag=0;
charch1;
while(((ch>47)&&(ch<58)))
{
CurrentToken.name[k++]=ch;
ch=fgetc(SourceFin);
if(ch=='.')
{
flag=1;
break;
}
}
CurrentToken.code=19;
CurrentToken.addr=addr_count++;
CurrentToken.label=label_count++;
if(flag)
{
ch1=fgetc(SourceFin);
if((ch1>47)&&(ch<58))CurrentToken.name[k++]=ch;
elseError
(2);
ch=ch1;
while((ch>47)&&(ch<58))
{
CurrentToken.name[k++]=ch;
ch=fgetc(SourceFin);
}
CurrentToken.code=20;
if(ch=='.')
{
Error
(2);
ch=fgetc(SourceFin);
while((ch>47)&&(ch<58))ch=fgetc(SourceFin);
}
}
if(((ch>64)&&(ch<90))||((ch>96)&&(ch<123)))
{
Error
(2);
while(((ch>64)&&(ch<90))||((ch>96)&&(ch<123)))
{
ch=fgetc(SourceFin);
while((ch>47)&&(ch<58))ch=fgetc(SourceFin);
}
}
OutPut();
}
/*************************字母处理************************************/
voidIsAlpha()
{
inti,h;
h=0;
i=0;
while(((ch>64)&&(ch<90))||((ch>96)&&(ch<123))||(ch=='_'))
{
CurrentToken.name[i++]=ch;
ch=fgetc(SourceFin);
}
for(i=1;i{
h=strcmp(CurrentToken.name,key[i].name);
if(!
h)
break;
}
if(!
h)
{
CurrentToken.code=key[i].code;
CurrentToken.addr=-1;
}
else
{
CurrentToken.code=18;
CurrentToken.addr=addr_count++;
}
CurrentToken.label=label_count++;
OutPut();
}
/****************************字符串处理*******************************/
voidIsChar()
{
inti=0;
for(;;)
{
ch=fgetc(SourceFin);
CurrentToken.code=20;
if(ch!
='\'')CurrentToken.name[i++]=ch;
elsebreak;
}
CurrentToken.addr=addr_count++;
CurrentToken.label=label_count++;
OutPut();
ch=fgetc(SourceFin);
}
/*****************************