编译原理实验报告汇总.docx
《编译原理实验报告汇总.docx》由会员分享,可在线阅读,更多相关《编译原理实验报告汇总.docx(72页珍藏版)》请在冰点文库上搜索。
编译原理实验报告汇总
编译原理实验报告
PL/0语言编译器分析
词法分析实验
递归下降语法分析实验
LL
(1)分析法语法分析实验
教师:
姓名:
班级:
学号:
PL/0语言编译器分析实验报告
一、实验目的
通过阅读与解析一个实际编译器(PL/0语言编译器)的源代码,加深对编译阶段(包括词法分析、语法分析、语义分析、中间代码生成等)和编译系统软件结构的理解,并达到提高学生学习兴趣的目的。
二、实验要求
(1)要求掌握基本的程序设计技巧(C语言)和阅读较大规模程序源代码的能力;
(2)理解并掌握编译过程的逻辑阶段及各逻辑阶段的功能;
(3)要求能把握整个系统(PL/0语言编译器)的体系结构,各功能模块的功能,各模块之间的接口;
(4)要求能总结出实现编译过程各逻辑阶段功能采用的具体算法与技术。
三、实验步骤
(1)根据PL/0语言的语法图,理解PL/0语言各级语法单位的结构,掌握PL/0语言合法程序的结构;
(2)从总体上分析整个系统的体系结构、各功能模块的功能、各模块之间的调用关系、各模块之间的接口;
(3)详细分析各子程序和函数的代码结构、程序流程、采用的主要算法及实现的功能;
(4)撰写分析报告,主要内容包括系统结构框图、模块接口、主要算法、各模块程序流程图等。
四、报告内容
1、PL/0语言语法的BNF表示-1,对语法描述图的解析
<程序>→<程序体>.
<程序体>→[<常量说明部分>][变量说明部分>][<过程说明部分>]<语句>
<常量说明部分>→const<常量定义>{,<常量定义>};
<常量定义>→<标识符>=<无符号整数>
<无符号整数>→<数字>{<数字>}
<变量说明部分>→var<标识符>{,<标识符>};
<标识符>→<字母>{<字母>|<数字>}
<过程说明部分>→<过程首部><程序体>{;<过程说明部分>};
<过程首部>→procedure<标识符>;
<语句>→<赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|
<复合语句>
<赋值语句>→<标识符>:
=<表达式>
<复合语句>→begin<语句序列>end
<语句序列>→<语句>{;<语句>}
<条件>→<表达式><关系运算符><表达式>|odd<表达式>
<表达式>→[+|-]<项>{<加法运算符><项>}
<项>→<因子>{<乘法运算符><因子>}
<因子>→<标识符>|<无符号整数>|'('<表达式>')'
<加法运算符>→+|-
<乘法运算符>→*|/
<关系运算符>→=|<>|<|<=|>|>=
<条件语句>→if<条件>then<语句>
<过程调用语句>→call<标识符>
<当型循环语句>→while<条件>do<语句>
<字母>→a|b|...|x|y|z
<数字>→0|1|2|...|8|9
2、PL/0编译程序的总体设计
•其编译过程采用一趟扫描方式
•以语法、语义分析程序为核心
•词法分析程序和代码生成程序都作为一个过程,
•当语法分析需要读单词时就调用词法分析程序,
•而当语法、语义分析正确,
•需要生成相应的目标代码时,则调用代码生成程序。
•表格管理程序实现变量,
•常量和过程标识符的信息的登录与查找。
•出错处理程序,
•对词法和语法、语义分析遇到的错误给出在源程序中出错的位置和与错误性质有关的编号,并进行错误恢复。
3、PL/0编译程序结构
目标程序
4、编译程序总体流程图
4、详细分析
4.1主要函数功能
4.2语法调用关系图
因子factor
Pl/0词法分析程序Getsym
识别的单词:
(类别,值)
保留字:
如:
BEGIN、END、IF、THEN等
运算符:
如:
+、-、*、/、:
=、#、>=、<=等
标识符:
用户定义的变量名、常数名、过程名
常数:
如:
10、25、100等整数
界符:
如:
‘,’、‘.’、‘;’、‘(’、‘)’等
Getsym用到三个单元:
SYM:
存放单词类别
ID:
存放标识符的值
NUM:
存放整数的值
词法分析过程GETSYM
所要完成的任务:
滤空格
识别保留字
识别标识符
拼数
识别单字符单词(<,>等)
拼双字符单词(<=,<>等)
输出源程序
读字符子程序(getch)
PL/0编译程序语法分析的设计与实现
自顶向下的语法分析
递归子程序法:
对于每个非终结符,编写一个子程序,由该子程序负责识别该语法单位是否正确。
递归子程序法
递归子程序法:
对应每个非终结符语法单元,,编一个独立的处理过程(或子程序)。
语法分析从读入第一个单词开始,由非终结符<程序>(即开始符)出发,沿语法描述图箭头所指出的方向进行分析。
当遇到非终结符时,则调用相应的处理过程,从语法描述图看,也就进入了一个语法单元,再沿当前所进入的语法单元所指箭头方向继续进行分析。
当遇到描述图中是终结符时,则判断当前读入的单词是否与图中的终结符相匹配,若匹配,再读取下一个单词继续分析。
遇到分支点时,将当前的单词与分支点上多个终结符逐个相比较,若都不匹配时可能是进入下一个非终结符语法单位或是出错。
〈表达式〉的递归子程序实现
procedureexpr;
begin
ifsymin[plus,minus]then
begingetsym;term;
end
elseterm;
whilesymin[plus,minus]do
begin
getsym;term;
end
end;
〈因子〉∷=〈标识符〉|〈无符号整数〉|‘(’〈表达式〉‘)’
〈因子〉的递归子程序实现
procedurefactor;
begin
ifsym<>identthen
begin
ifsym<>numberthen
begin
ifsym=‘(‘then
begin
getsym;
expr;
ifsym=‘)’then
getsym
elseerror
end
elseerror
end
elsegetsym
end
elsegetsym
end;
说明部分的分析与处理
对每个过程(含主程序)说明的对象(变量,常量和过程)造符号表,登录标识符的属性。
标识符的属性:
种类,所在层次,值和分配的相对位置。
登录信息由ENTER过程完成。
常量定义语句的处理语法:
<常量说明部分>:
:
=const<常量定义>{,<常量定义>};
<常量定义>:
:
=<标识符>=<无符号整数>
<无符号整数>:
:
=<数字>{<数字>}
ifsym=constsymthen
begin
getsym;(*获取下一个token,正常应为用作常量名的标识符*)
repeat(*反复进行常量声明*)
constdeclaration;(*声明以当前token为标识符的常量*)
whilesym=commado(*如果遇到了逗号则反复声明下一常量*)
begin
getsym;(*获取下一个token,这里正好应该是标识符*)
constdeclaration(*声明以当前token为标识符的常量*)
end;
ifsym=semicolonthen(*如果常量声明结束,应遇到分号*)
getsym(*获取下一个token,为下一轮循环做好准备*)
else
error(5)(*提示5号错误*)
untilsym<>ident(*如果遇到非标识符,则常量声明结束*)
end;
常量说明处理
procedureconstdeclaration;
begin
ifsym=identthen
begin
getsym;
ifsymin[eql,becomes]then(*如果是等号或赋值号*)
ifsym=becomesthen(*如果是赋值号(常量生明中应该是等号)*)
error
(1);(*提示1号错误*)
getsym;(*获取下一个token,等号或赋值号后应接上数字*)
ifsym=numberthen(*如果的确是数字*)
begin
enter(constant);(*把这个常量登陆到符号表*)
getsym(*获取下一个token,为后面作准备*)
end
elseerror
(2)(*如果等号后接的不是数字,提示2号错误*)
elseerror(3)(*如常量标识符后不是等号或赋值号,提示3号错误*)
end
elseerror(4)
end(*constdeclaration*);
变量定义语句的处理语法:
<变量说明部分>:
:
=var<标识符>{,<标识符>};
ifsym=varsymthen
begin
getsym;
repeat
vardeclaration;(*变量说明处理*)
whilesym=commado
begin
getsym;
vardeclaration
end;
ifsym=semicolonthen
getsym
elseerror(5)
untilsym<>ident;
end;
变量说明处理procedureardeclaration;
begin
ifsym=identthen
begin
enter(variable);
getsym
end
elseerror(4)
end(*vardeclaration*);
过程定义语句的处理程序:
whilesym=procsymdo(*循环声明各子过程*)
begin
getsym;(*获取下一个token,此处正常应为作为过程名的标识符*)
ifsym=identthen(*如果token确为标识符*)
begin
enter(procedur);(*把这个过程登录到名字表中*)
getsym(*获取下一个token,正常情况应为分号*)
end
else
error(4);(*否则提示4号错误*)
ifsym=semicolonthen(*如果当前token为分号*)
getsym(*获取下一个token,准备进行语法分析的递归调用*)
else
error(5);(*否则提示5号错误*)
目标代码结构和代码生成
代码生成代码生成是由过程GEN完成。
GEN有3个参数,分别代表目标代码的功能码,层差和位移量。
PL/0编译程序的语法错误处理
在进入某个语法单位时,调用TEST,检查当前符号是否属于该语法单位的开始符号集合。
若不属于,则滤去开始符号和后继符号集合外的所有符号。
在语法单位分析结束时,调用TEST,检查当前符号是否属于调用该语法单位时应有的后继符号集合。
若不属于,则滤去后继符号和开始符号集合外的所有符号。
解释执行的流程图
返回
词法分析实验报告
一、实验目的
1、加深对词法分析理论的理解,培养动手实践的能力。
词法分析的功能:
扫描源程序字符流,按照源语言的词法规则识别出各类单词版本号,并产生用于语法分析的符号序列,即将字符串源程序转换成符号串源程序.
2、巩固和加深对线性表、栈、队列、字符串、树、图、查找、排序等理论知识的理解。
3、掌握现实复杂问题的分析建模和解决方法(包括问题描述、系统分析、设计建模、代码实现、结果分析等)。
4、提高利用计算机分析解决综合性实际问题的基本能力。
二、实验内容与设计思想
内容:
编写一个词法分析程序,并进行简单的词法进行分析.
设计思想:
编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值,并促留在文件中。
三、详细设计
#include
#include
#include
#include
#defineBAOLZ1
#defineBIAOSF2
#defineCHANGS3
#defineYUNSF4
#defineFENGF5
char*baoliuzi[10]={"if","int","for","while","do","return","break","continue","main","void"};
char*yunsuanfu[5]={"+","-","*","/","="};
char*fengefu[6]={",",";","{","}","(",")"};
//函数声明
intisnumber(charch);
intiszimu(charch);
voidscanner();
voidmain()//主函数
{
scanner();
}
///*************************************************************///
voidscanner()//词法分析程序算法
{inti=0;
charch;
FILE*fpin;
FILE*fpout;
//文件操作
if((fpin=fopen("shiyan1in.txt","r"))==NULL)
{printf("cannotopenthefile");
}
if((fpout=fopen("shiyan1out.txt","w+"))==NULL)
{printf("cannotopenthefile");
}//获取文件的第一个字符
ch=fgetc(fpin);//读取近来的字符进行判断
while(ch!
=EOF)
{inta,b;
charbuffer[20]={'\0'};//暂时存储从文件读来的字符及其对每次buffer都进行清空
if(ch=='10'||ch=='13'||ch=='09'||ch=='')//对空格进行过滤
ch=fgetc(fpin);
a=iszimu(ch);//a表示字母函数的返回值
b=isnumber(ch);//b表示数字函数的返回值
//****************************************************************
//判断标识符和保留字
if(a==1)
{intr1;
intj=0;
while(a)
{intm,n;
m=iszimu(ch);//m表示字母函数的返回值
n=isnumber(ch);//n表示数字函数的返回值
if(m==1||n==1)
{buffer[j]=ch;
ch=fgetc(fpin);
j++;
}
elsebreak;
}
for(i=0;i<10;i++)
{
r1=strcmp(baoliuzi[i],buffer);
if(r1==0)
{
printf("%s是保留字\n",buffer);//输出到界面上
fprintf(fpout,"(%i,\"%s\")\n",BAOLZ,buffer);///输出到文件
break;
}
}
if(r1!
=0)
{
printf("%s是字符\n",buffer);
fprintf(fpout,"(%i,\"%s\")\n",BIAOSF,buffer);
}
continue;//接受下一个字符串
}
//*****************************************************************
//判断是数字b表示数字函数的返回值
elseif(b==1)
{
intj=0;
while(b)
{
intm,n;
m=iszimu(ch);
n=isnumber(ch);
if(n==1)
{buffer[j]=ch;
ch=fgetc(fpin);
j++;
}
elsebreak;
}
printf("%s是数字\n",buffer);
fprintf(fpout,"(%i,\"%s\")\n",CHANGS,buffer);///输出到文件
continue;
}
//******************************************************************
//判断是运算符或者是界符
else
intr1,r2;
buffer[0]=ch;
for(i=0;i<5;i++)
r1=strcmp(yunsuanfu[i],buffer);
if(r1==0)
{printf("%s是运算符\n",buffer);
fprintf(fpout,"(%i,\"%s\")\n",YUNSF,buffer);///输出到文件
break;
}
}
for(i=0;i<6;i++)
{r2=strcmp(fengefu[i],buffer);
if(r2==0){
printf("%s是界符\n",buffer);
fprintf(fpout,"(%i,\"%s\")\n",FENGF,buffer);///输出到文件
break;
}
}
ch=fgetc(fpin);
continue;
}
}
fclose(fpin);
fclose(fpout);
}
//******************************************************************
//判断一个字符是否是字母
intiszimu(charch)
{
intflag=0;
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
flag=1;
returnflag;
}
//******************************************************************
//判断一个字符是否是字母
intisnumber(charch)
{
intflag=0;
if(ch>='0'&&ch<='9')
flag=1;
returnflag;
}
四、流程图
结束
五、运行结果
文件输出:
六、心得体会:
通过该实验,主要有以下几方面收获:
一、对实验原理有更深的理解。
二、然后可以先写出程序的函数定义,每个函数实现相应的功能,再用这些函数写出主程序模块。
三、通过本次编译原理课程设计,激发了我学习的积极性,培养了我独立发现问题、分析问题,解决问题的能力。
更增强我与同学交流沟通和共同解决问题合作的能力。
四、模块化思想是程序设计中一个十分重要部分,它可以把一个程序分成若干部分,然后分块进行编写,它可以大大减少我们因疏忽造成返工时的时间等等。
递归下降语法分析实验报告
一、实验目的
根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对递归下降分析法的理解。
注:
也可以采用预测分析方法、算符优先分析方法来进行分析。
具体参照课本上的说明,以下是递归下降分析法的介绍。
二、实验内容与设计思想
编写一个小的语法分析程序,并进行简单的词法进行分析.
三详细设计
#include
#include
#include
typedefstruct
{charR;charr;intflag;}array;typedefstruct
{charE;chare;}charLode;typedefstruct
charLode*base;inttop;
charstr[80][80],arr[80][80],brr[80][80];arrayF[20];
intm,kk,p,ppp,FF=1;charr[10];
intcrr[20][20],FLAG=0;charccrr1[1][20],ccrr2[20][1];
voidInitstack(charstack&s)//定义栈
{s.base=newcharLode[20];s.top=-1;}
voidpush(charstack&s,charLodew)
{s.top++;s.base[s.top].E=w.E;
s.base[s.top].e=w.e;}
voidpop(charstack&s,charLode&w)
{w.E=s.base[s.top].E;w.e=s.base[s.top].e;s.top--;
}intIsEmpty(charstacks)
{if(s.top==-1return1;elsereturn0;}
intIsLetter(charch)
{if(ch>='A'&&ch<='Z')return1;
elsereturn0;
}
//judge1是判断是否是算符文法:
若产生式中含有两个相继的非终结符则不是算符文法
intjudge1(intn)
{intj=3,flag=0;
for(inti=0;i<=n;i++)while(str[i][j]!
='\0')
{chara=str[i][j];charb=str[i][j+1];
if(IsLetter(a)&&IsLetter(b))
{flag=1;break;}elsej++;
}if(flag==1)return0;elsereturn1;
}
//judge2是判