编译原理实验报告_第1页
编译原理实验报告_第2页
编译原理实验报告_第3页
编译原理实验报告_第4页
编译原理实验报告_第5页
已阅读5页,还剩89页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、编译原理实验报告 PL/0 语言编译器分析 词法分析实验 递归下降语法分析实验 LL(1)分析法语法分析实验 教师: 姓名: 班级: 学号:PL/0 语言编译器分析实验报告一、实验目的 通过阅读与解析一个实际编译器(PL/0语言编译器)的源代码, 加深对编译阶段(包括词法分析、语法分析、语义分析、中间代 码生成等)和编译系统软件结构的理解,并达到提高学生学习兴趣的目的。 二、实验要求 (1)要求掌握基本的程序设计技巧(C语言)和阅读较大规模程序 源代码的能力; (2)理解并掌握编译过程的逻辑阶段及各逻辑阶段的功能; (3)要求能把握整个系统(PL/0语言编译器)的体系结构,各功能 模块的功能,

2、各模块之间的接口; (4)要求能总结出实现编译过程各逻辑阶段功能采用的具体算法与技术。 三、实验步骤 (1) 根据PL/0语言的语法图,理解PL/0语言各级语法单位的结构,掌握PL/0语言合法程序的结构; (2)从总体上分析整个系统的体系结构、各功能模块的功能、各模块之间的调用关系、各模块之间的接口; (3)详细分析各子程序和函数的代码结构、程序流程、采用的主要算法及实现的功能; (4)撰写分析报告,主要内容包括系统结构框图、模块接口、主要算法、各模块程序流程图等。四、报告内容1、 PL/0 语言语法的 BNF 表示-1,对语法描述图的解析 . 变量说明部分 const ,; = var ,;

3、 | ; procedure ; | := begin end ; | odd +|- |() +|- *|/ =|= if then call while do a|b|.|x|y|z 0|1|2|.|8|92、PL/0编译程序的总体设计 其编译过程采用一趟扫描方式以语法、语义分析程序为核心词法分析程序和代码生成程序都作为一个过程,当语法分析需要读单词时就调用词法分析程序,而当语法、语义分析正确,需要生成相应的目标代码时,则调用代码生成程序。表格管理程序实现变量,常量和过程标识符的信息的登录与查找。出错处理程序, 对词法和语法、语义分析遇到的错误给出在源程序中出错的位置和与错误性质有关的编号

4、,并进行错误恢复。3、PL/0编译程序结构 词法分析程序语法语义分析程序代码生成程序表格管理程序出错处理程序PL/0源程序目标程序4、编译程序总体流程图 4、详细分析4.1 主要函数功能4.2 语法调用关系图 程序 pl0分程序block语句statement条件condition表达式项 term因子 factorPl/0词法分析程序Getsym识别的单词: (类别,值) 保留字:如:BEGIN、 END、 IF、 THEN等 运算符: 如:+、-、*、/、:=、#、=、=等 标识符: 用户定义的变量名、常数名、过程名 常数: 如:10、25、100等整数 界符: 如:,、. 、; 、( 、

5、)等 Getsym用到三个单元: SYM:存放单词类别 ID:存放标识符的值 NUM:存放整数的值 词法分析过程GETSYM 所要完成的任务: 滤空格 识别保留字 识别标识符 拼数 识别单字符单词(等) 拼双字符单词(=,等) 输出源程序 读字符子程序(getch) PL/0编译程序语法分析的设计与实现 自顶向下的语法分析 递归子程序法:对于每个非终结符,编写一个子程序,由该子程序负责识别该语法单位是否正确。 递归子程序法递归子程序法:对应每个非终结符语法单元,编一个独立的处理过程(或子程序)。语法分析从读入第一个单词开始,由非终结符(即开始符)出发,沿语法描述图箭头所指出的方向进行分析。当遇

6、到非终结符时,则调用相应的处理过程,从语法描述图看,也就进入了一个语法单元,再沿当前所进入的语法单元所指箭头方向继续进行分析。当遇到描述图中是终结符时,则判断当前读入的单词是否与图中的终结符相匹配,若匹配,再读取下一个单词继续分析。遇到分支点时,将当前的单词与分支点上多个终结符逐个相比较,若都不匹配时可能是进入下一个非终结符语法单位或是出错。 表达式的递归子程序实现 procedure expr; begin if sym in plus, minus then begin getsym; term; end else term; while sym in plus, minus do beg

7、in getsym; term; end end;因子=标识符|无符号整数|(表达式) 因子的递归子程序实现procedure factor;begin if sym ident then begin if sym number then begin if sym = ( then begin getsym; expr; if sym = ) then getsym else error end else error end else getsym end else getsym end;说明部分的分析与处理 对每个过程(含主程序)说明的对象(变量,常量和过程)造符号表, 登录标识符的属性。标

8、识符的属性:种类,所在层次,值和分配的相对位置。登录信息由ENTER过程完成。 常量定义语句的处理语法:: := const , ;: := =: := if sym = constsym then begin getsym; (* 获取下一个token,正常应为用作常量名的标识符 *) repeat (* 反复进行常量声明 *) constdeclaration; (* 声明以当前token为标识符的常量 *) while sym = comma do (* 如果遇到了逗号则反复声明下一常量*) begin getsym; (* 获取下一个token,这里正好应该是标识符 *) constd

9、eclaration (* 声明以当前token为标识符的常量 *) end; if sym = semicolon then (* 如果常量声明结束,应遇到分号 *) getsym (* 获取下一个token,为下一轮循环做好准备 *) else error(5) (*提示5号错误 *) until sym ident (* 如果遇到非标识符,则常量声明结束 *) end; 常量说明处理 procedure constdeclaration; begin if sym = ident then begin getsym; if sym in eql, becomes then (* 如果是等

10、号或赋值号 *) if sym = becomes then (* 如果是赋值号(常量生明中应该是等号) *) error(1); (* 提示1号错误 *) getsym; (* 获取下一个token,等号或赋值号后应接上数字 *) if sym = number then (* 如果的确是数字 *) begin enter(constant); (* 把这个常量登陆到符号表 *) getsym (* 获取下一个token,为后面作准备 *) end else error(2) (* 如果等号后接的不是数字,提示2号错误 *) else error(3)(* 如常量标识符后不是等号或赋值号,提

11、示3号错误 *) end else error(4) end(* constdeclaration *);变量定义语句的处理语法:: := var , ; if sym=varsym then begin getsym; repeat vardeclaration;(*变量说明处理*) while sym=comma do begin getsym; vardeclaration end; if sym=semicolon then getsym else error(5) until symident; end;变量说明处理procedure ardeclaration; begin if

12、sym=ident then begin enter(variable); getsym end else error(4) end(*vardeclaration*);过程定义语句的处理程序: while sym = procsym do (* 循环声明各子过程 *) begin getsym; (* 获取下一个token,此处正常应为作为过程名的标识符 *) if sym = ident then (* 如果token确为标识符 *) begin enter(procedur); (* 把这个过程登录到名字表中 *) getsym (* 获取下一个token,正常情况应为分号 *) end

13、 else error(4); (* 否则提示4号错误 *) if sym = semicolon then (* 如果当前token为分号 *) getsym (* 获取下一个token,准备进行语法分析的递归调用 *) else error(5); (* 否则提示5号错误 *)目标代码结构和代码生成代码生成代码生成是由过程GEN完成。GEN有3个参数,分别代表目标代码的功能码,层差和位移量。PL/0编译程序的语法错误处理在进入某个语法单位时,调用TEST,检查当前符号是否属于该语法单位的开始符号集合。若不属于,则滤去开始符号和后继符号集合外的所有符号。 在语法单位分析结束时,调用TEST,

14、检查当前符号是否属于调用该语法单位时应有的后继符号集合。若不属于,则滤去后继符号和开始符号集合外的所有符号。 解释执行的流程图interpret三个寄存器赋初值 t:=0;b:=1;p:=0;主程序的SL,DL,RA赋初值s1:=0; s2=0; s3=0;i:=codep;p:=p+1;执行指令iP=0?返回 词法分析实验报告一 、实验目的1、加深对词法分析理论的理解,培养动手实践的能力。词法分析的功能:扫描源程序字符流,按照源语言的词法规则识别出各类单词版本号,并产生用于语法分析的符号序列,即将字符串源程序转换成符号串源程序.2、巩固和加深对线性表、栈、队列、字符串、树、图、查找、排序等理

15、论知识的理解。3、掌握现实复杂问题的分析建模和解决方法(包括问题描述、系统分析、设计建模、代码实现、结果分析等)。4、提高利用计算机分析解决综合性实际问题的基本能力。二 、实验内容与设计思想内容: 编写一个词法分析程序,并进行简单的词法进行分析.设计思想: 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值,并促留在文件中。三、详细设计#include #include #include #include #define BAOLZ 1#define BIAOSF 2#define

16、CHANGS 3#define YUNSF 4#define FENGF 5char * baoliuzi10=if,int,for,while,do,return,break,continue,main,void;char * yunsuanfu5=+,-,*,/,=;char * fengefu6=,;,(,);/函数声明int isnumber(char ch);int iszimu(char ch);void scanner();void main() /主函数 scanner();/*/void scanner()/词法分析程序算法int i=0;char ch;FILE * fpi

17、n;FILE * fpout; /文件操作if (fpin=fopen(shiyan1in.txt,r)=NULL) printf (cannot open the file);if(fpout=fopen(shiyan1out.txt,w+)=NULL) printf (cannot open the file); /获取文件的第一个字符 ch=fgetc(fpin); /读取近来的字符进行判断while(ch!=EOF) int a,b; char buffer20=0; /暂时存储从文件读来的字符及其对每次buffer都进行清空 if(ch=10|ch=13|ch=09|ch= ) /对

18、空格进行过滤 ch=fgetc(fpin); a=iszimu(ch); /a表示字母函数的返回值 b=isnumber(ch); /b表示数字函数的返回值 /* /判断标识符和保留字 if(a=1) int r1; int j=0; while(a) int m,n; m=iszimu(ch); / m表示字母函数的返回值 n=isnumber(ch); /n表示数字函数的返回值 if(m=1|n=1) bufferj=ch; ch=fgetc(fpin); j+;else break; for(i=0;i10;i+) r1=strcmp(baoliuzii,buffer); if(r1=0

19、) 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表示数字函数的返回值else if(b=1) int j=0; while(b) int m,n; m=iszimu(ch); n=isnumber(ch); if(n=1) bufferj=ch; ch=fgetc(fpi

20、n); j+; else break; printf(%s是数字n,buffer); fprintf(fpout,(%i,%s)n,CHANGS,buffer); /输出到文件 continue; /*/判断是运算符或者是界符else int r1,r2; buffer0=ch; for(i=0;i5;i+) r1=strcmp(yunsuanfui,buffer); if(r1=0) printf(%s是运算符n,buffer); fprintf(fpout,(%i,%s)n,YUNSF,buffer); /输出到文件 break; for(i=0;i= a & ch=A & ch=0 &

21、ch=9) flag=1; return flag; 四、流程图开始读入程序判断类型保留字标识符运算符分辜负文件输出结束五、运行结果文件输出:六、心得体会:通过该实验,主要有以下几方面收获: 一、 对实验原理有更深的理解。二、然后可以先写出程序的函数定义,每个函数实现相应的功能,再用这些函数写出主程序模块。三、 通过本次编译原理课程设计,激发了我学习的积极性,培养了我独立发现问题、分析问题,解决问题的能力。更增强我与同学交流沟通和共同解决问题合作的能力。四、模块化思想是程序设计中一个十分重要部分,它可以把一个程序分成若干部分,然后分块进行编写,它可以大大减少我们因疏忽造成返工时的时间等等。 递

22、归下降语法分析实验报告一、实验目的根据某一文法编制调试递归下降分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对递归下降分析法的理解。注:也可以采用预测分析方法、算符优先分析方法来进行分析。具体参照课本上的说明,以下是递归下降分析法的介绍。二 、实验内容与设计思想 编写一个小的语法分析程序,并进行简单的词法进行分析.三详细设计#include#include#includetypedef structchar R;char r;int flag;array;typedef struct char E;char e;charLode;typedef struct charLod

23、e *base; int top;char str8080,arr8080,brr8080;array F20;int m,kk,p,ppp,FF=1;char r10;int crr2020,FLAG=0;char ccrr1120,ccrr2201;void Initstack(charstack &s)/定义栈s.base=new charLode20;s.top=-1;void push(charstack &s,charLode w) s.top+;s.bases.top.E=w.E; s.bases.top.e=w.e;void pop(charstack &s,charLode

24、&w) w.E=s.bases.top.E;w.e=s.bases.top.e; s.top-;int IsEmpty(charstack s)if(s.top=-1 return 1;else return 0;int IsLetter(char ch)if(ch=A&ch=Z) return 1; else return 0;/judge1是判断是否是算符文法:若产生式中含有两个相继的非终结符则不是算符文法int judge1(int n)int j=3,flag=0;for(int i=0;i=n;i+) while(strij!=0) char a=strij;char b=strij

25、+1; if(IsLetter(a)&IsLetter(b) flag=1;break;else j+; if(flag=1)return 0;else return 1;/judge2是判断文法G是否为算符优先文法:若不是算符文法或若文法中含空字或终结符的优先级不唯一则不是算符优先文法void judge2(int n)for(int i=0;i=n;i+) if(stri3=|judge1(n)=0|FLAG=1)/代表空字 cout文法G不是算符优先文法!n)cout文法G是算符优先文法!endl;/search1是查看存放终结符的数组r中是否含有重复的终结符int search1(ch

26、ar r,int kk,char a)for(int i=0;ikk;i+) if(ri=a)break; if(i=kk) return 0;else return 1;/createF函数是用F数组存放每个终结符与非终结符和组合,并且值每队的标志位为0;F数组是一个结构体void createF(int n)int k=0,i=1;char g;char t10;/t数组用来存放非终结符t0=str00;while(i=n)if(tk!=stri0) k+;tk=stri0;g=tk;i+; else i+;kk=0;char c;for(i=0;i=n;i+) int j=3; whil

27、e(strij!=0) c=strij;if(IsLetter(c)=0) if(!search1(r,kk,c) rkk=c;kk+;/r数组用来存放终结符 j+; m=0;for(i=0;ik;i+) for(int j=0;jkk-1;j+) Fm.R=ti;Fm.r=rj;Fm.flag=0; m+; /search函数是将在F数组中寻找到的终结符与非终结符对的标志位值为1void search(charLode w)for(int i=0;im;i+) if(Fi.R=w.E&Fi.r=w.e)Fi.flag=1;break;void FirstVT(int n)/求FirstVTc

28、harstack sta;charLode w;int i=0;Initstack(sta);while(i=n) int k=3; w.E=stri0;char a=strik; char b=strik+1; if(!IsLetter(a)/产生式的后选式的第一个字符就是终结符的情况 w.e=a;push(sta,w);search(w); i+; else if(IsLetter(a)&b!=0&!IsLetter(b)/产生式的后选式的第一个字符是非终结符的情况 w.e=b; push(sta,w);search(w);i+; else i+;charLode ww;while(!Is

29、Empty(sta)pop(sta,ww); for(i=0;i=n;i+) w.E=stri0;if(stri3=ww.E&stri4=0) w.e=ww.e;push(sta,w);search(w); break; p=0;int k=1;i=1;while(im) if(Fi-1.flag=1) arrp0=Fi-1.R;arrpk=Fi-1.r; while(Fi.flag=0&im) i+ if(Fi.flag=1) if(Fi.R=arrp0) k+; else arrpk+1=0;p+;k=1;i+; void LastVT(int n)/求LastVTcharstack st

30、a;charLode w;for(int i=0;im;i+) Fi.flag=0;i=0;Initstack(sta);while(i=n) int k=strlen(stri);w.E=stri0;char a=strik-1;char b=strik-2;if(!IsLetter(a) w.e=a;push(sta,w);search(w); i+;else if(IsLetter(a)&!IsLetter(b) w.e=b; push(sta,w);search(w)i+;else i+;charLode ee;while(!IsEmpty(sta)pop(sta,ee);for(i=

31、0;i=n;i+) w.E=stri0; if(stri3=ee.E&stri4=0) w.e=ee.e;push(sta,w);search(w); int k=1;i=1;ppp=0;while(im)if(Fi-1.flag=1) brrppp0=Fi-1.R; brrpppk=Fi-1.r; while(Fi.flag=0&im) i+; if(Fi.flag=1) if(Fi.R=arrppp0 k+; else brrpppk+1=0;ppp+;k=1; i+; void createYXB(int n)/构造优先表int i,j; for(j=1;j=kk;j+)ccrr10j=

32、rj-1;for( i=1;i=kk;i+) ccrr2i0=ri-1;for(i=1;i=kk;i+)for(j=1;j=kk;j+) crrij=0;int I=0,J=3;while(I=n) if(strIJ+1=0) I+;J=3;Elsewhile(strIJ+1!=0) char aa=strIJ; char bb=strIJ+1;if(!IsLetter(aa)&!IsLetter(bb)/优先及等于的情况,用1值表示等于 for(i=1;i=kk;i+) if(ccrr2i0=aa) break; for(j=1;j=kk;j+) if(ccrr10j=bb)break; i

33、f(crrij=0) crrij=1;else FLAG=1;I=n+1; J+; if(!IsLetter(aa)&IsLetter(bb)&strIJ+2!=0&!IsLetter(strIJ+2)/优先及等于的情况 for(i=1;i=kk;i+) if(ccrr2i0=aa)break; for(int j=1;j=kk;j+) if(ccrr10j=strIJ+2)break; if(crrij=0) crrij=1;else FLAG=1;I=n+1; if(!IsLetter(aa)&IsLetter(bb)/优先及小于的情况,用2值表示小于 for(i=1;i=kk;i+) i

34、f(aa=ccrr2i0) break; for(j=0;j=p;j+) if(bb=arrj0) break;for(int mm=1;arrjmm!=0;mm+) for(int pp=1;pp=kk;pp+) if(ccrr10pp=arrjmm) break; if(crripp=0) crripp=2;else FLAG=1;I=n+1; J+; if(IsLetter(aa)&!IsLetter(bb)/优先及大于的情况,用3值表示大于 for(i=1;i=kk;i+) if(ccrr10i=bb) break;for(j=0;j=ppp;j+) if(aa=brrj0 break

35、; for(int mm=1;brrjmm!=0;mm+) for(int pp=1;pp=kk;pp+) if(ccrr2pp0=brrjmm) break; if(crrppi=0) crrppi=3;else FLAG=1;I=n+1; J+; /judge3是用来返回在归约过程中两个非终结符相比较的值int judge3(char s,char a)int i=1,j=1;while(ccrr2i0!=s) i+;while(ccrr10j!=a) j+;if(crrij=3) return 3else if(crrij=2) return 2;else if(crrij=1) ret

36、urn 1;else return 0;void print(char s,char STR20,int q,int u,int ii,int k)/打印归约的过程coutu ;for(int i=0;i=k;i+) coutsi;cout ;for(i=q;i=ii;i+) coutSTR0i;cout ;void process(char STR20,int ii)/对输入的字符串进行归约的过程 cout步骤 符号栈 输入串 动作endl;int k=0,q=0,u=0,b,i,j;char s40,a;sk=#;print(s,STR,q,u,ii,k);cout预备endl;k+;u+ sk=STR0q;q+;print(s,STR,q,u,ii,k);cout移进endl;while(q=ii) a=STR0q; if(!IsLetter(sk) j=k; else j=k-1; b=judge3(sj,a); if(b=3)/大于的情况进行归约 while(IsLetter(sj-1) j-; for(i=j;i=k;i+) si=0; k=j;sk=N;u+; print(s,STR,q,u,ii,k); cout归约endl; else if(b=2|b=1)/小于或等于的情况移进 k+; sk=a;u+; q+;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论