编译实验报告文档格式.docx
《编译实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《编译实验报告文档格式.docx(77页珍藏版)》请在冰点文库上搜索。
If(flag=1)
{if(当前字符为数字)
{记录当前数字;
while(当前字符为数字)
{记录字符;
记单词编码为实数的编码(当前Token为实数);
elseError
(2);
if(当前字符为’.’)删除余下数字;
if(当前字符为字母)舍去后面的部分;
OutPut();
1.4IsChar()
识别字符串。
2.算法描述:
voidIsChar()
{for(;
;
)
{读取下一字符;
现行Token为字符串;
If(当前字符不是‘.’号)
记录字符;
Elsebreak;
读下一字符;
1.5IsOther()
识别其他单词。
voidIsOther()
{switch(当前字符)
{对于不同字符做出不同处理,主要有:
1、符号内容的记取;
2、查出机内码;
3、调用OutPut()输出至Token()文件;
4、读取下一字符;
5、对于错误符号将其删除,并报错;
1.6ScannerInit()
进行初始化,主要包括:
1、建立单词编码表、token表、符号表,并将它们清空。
2、打开单词编码文件,并将单词编码读到编码表中。
1.7OutPut()
输出识别出的单词,包括:
2.若单词为标识符或常数再查,填符号表。
1.8Error()
1.功能:
判断错误原因。
2.在由词法分析程序对L语言源程序分析产生的token,符号表文件的基础上,从完成语法语义分析,并产生相应的中间代码-四元式序列。
2.1paser()
主模块,完成初始化,并调用复合语句分析模块和说明语句分析模块,完成分析任务。
voidpaser()
{初始化;
从Token文件读取第一个单词;
if(单词==program)
{读取下一单词;
if(单词==标识符)
if(单词为‘;
’)
{行数加一;
读取下一单词;
if(单词为var)
declear();
if(单词为begin)
{S_Begin();
if(code不是等于号)Error(49);
else出错处理;
else出错处理;
2.2S_Begin()
完成复合语句的分析。
2.算法描述
S_Begin()
{if(当前字符为begin)
调用L_Analize();
if(当前字符为end)结束;
else非正常结束,返回0;
读取下一字符;
返回;
2.3L_Analize()
完成语句序列分析。
L_Analize()
{intrtn;
switch(当前字符)
{caseIF:
调用S_IF()函数;
break;
caseBEGIN:
调用S_Begin()函数;
braek;
case标识符:
调用S_Let()函数;
break;
caseWHILE:
调用S_While();
if(当前字符为‘:
{行数加一;
递归调用L_Analize()
elsereturnrtn;
2.4S_Let()
完成赋值语句的分析。
2.算法分析
S_Let(inta)
{if(当前字符为标识符)
{if(需要记录变量的地址)记录赋值变量的地址;
读取下一个单词;
if(当前单词为赋值号)
{调用表达式分析函数L_Analize();
if(表达式正确)生成赋值句四元式;
else赋值句出错;
return四元式序号;
2.5S_IF()
完成条件语句的分析。
IntS_IF()
{inta;
intrtn=0;
定义一个真出口True_address和一个假出口Flase_address;
if(当前单词为if)
{布尔表达式初始化;
调用布尔表达式分析函数B_Analize();
rtn=布尔表达式的四元式首址;
产生无条件跳转四元式;
if(当前单词为then)
switch(当前单词)
BackPatch();
if(当前单词为else)
BackPatch();
}
elsertn;
else报错;
(缺少then)
rtn;
2.6S_While()
完成while循环语句的分析。
2.算法描述;
intS_While()
{intrtn=0;
boor_value,True_address,False_address;
if(当前单词为while)
{rtn=布尔表达式分析函数B_Analize();
boor_value=布尔表达式值地址;
产生跳转四元式;
if(当前单词为do)
switch(当前单词)
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<
stdio.h>
#include<
string.h>
stdlib.h>
#defineLENGTH61
#defineN100
/*********************************************************************/
typedefstructtoken
{
intlabel;
charname[30];
intcode;
intaddr;
}token;
typedefstructKeyWord
}KeyWord;
typedefstructsymble
intnumber;
inttype;
}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<
N;
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("
***************************************"
*L语言词法分析器);
输入原文件名:
"
scanf("
%c"
&
filename[i]);
if(filename[i]==10)
break;
i++;
filename[i]='
if((SourceFin=fopen(filename,"
rt"
))==NULL)
printf("
无法打开文件%s.\n"
filename);
exit
(1);
if((TokenFout=fopen("
token.txt"
"
wt+"
无法打开文件symble.txt\n"
if((SymbleFout=fopen("
symble.txt"
ch=fgetc(SourceFin);
while(ch!
for(i=0;
i++)CurrentToken.name[i]='
if((ch>
47)&
&
(ch<
58))IsNumber();
else
{
if(((ch>
64)&
90))||((ch>
96)&
123))||(ch=='
_'
))IsAlpha();
else{if(ch=='
\'
'
)IsChar();
elseIsOther();
}
}
fclose(SourceFin);
fclose(TokenFout);
fclose(SymbleFout);
分析完毕/\n"
/********************************初始化*******************************/
voidScannerInit()
inti=1;
intk=0;
if((KeyFin=fopen("
ni.txt"
cannotopenni.txt\n"
60;
for(k=0;
k<
k++)key[i].name[k]='
{
/*读入编码表*/
fscanf(KeyFin,"
%s%d"
key[i].name,&
key[i].code);
}
fclose(KeyFin);
/*****************************数字处理********************************/
voidIsNumber()
charch1;
while(((ch>
58)))
CurrentToken.name[k++]=ch;
ch=fgetc(SourceFin);
if(ch=='
.'
flag=1;
CurrentToken.code=19;
CurrentToken.addr=addr_count++;
CurrentToken.label=label_count++;
if(flag)
ch1=fgetc(SourceFin);
if((ch1>
58))CurrentToken.name[k++]=ch;
elseError
(2);
ch=ch1;
while((ch>
58))
CurrentToken.name[k++]=ch;
ch=fgetc(SourceFin);
CurrentToken.code=20;
Error
(2);
while((ch>
58))ch=fgetc(SourceFin);
if(((ch>
123)))
Error
(2);
while(((ch>
OutPut();
/*************************字母处理************************************/
voidIsAlpha()
inti,h;
h=0;
i=0;
))
CurrentToken.name[i++]=ch;
for(i=1;
LENGTH;
h=strcmp(CurrentToken.name,key[i].name);
if(!
h)
if(!
CurrentToken.code=key[i].code;
CurrentToken.addr=-1;
else
CurrentToken.code=18;
CurrentToken.addr=addr_count++;
/****************************字符串处理*******************************/
voidIsChar()
if(ch!
='
)CurrentToken.name[i++]=ch;
elsebreak;
/*****************************