编译原理课程设计实验报告.docx
- 文档编号:2022646
- 上传时间:2022-10-26
- 格式:DOCX
- 页数:29
- 大小:50.94KB
编译原理课程设计实验报告.docx
《编译原理课程设计实验报告.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计实验报告.docx(29页珍藏版)》请在冰豆网上搜索。
编译原理课程设计实验报告
编译原理课程设计实验报告
实验目的:
这个实验的目的是构造Cminus语言的编译器,要求能够编译Cminus语言的程序并且生成中间代码。
在实验的过程中,学会使用flex/bison这两个重要的工具。
实验内容:
参见教材p491appendixA.
设计一cminus语言编译器
语言介绍。
Decaf(cminus)语言的关键字:
intwhileifelsereturnvoid
运算符:
+-*/><=,.!
={}[]<=>===()
Cminus语言的限制。
数字:
支持10进制整数。
小数可以采用科学记数法,如1E3也是合法的。
字符串:
字符串内部不允许出现换行,即字符串变量必须在同一行内。
注释:
Cminus语言允许采用/*…*/注释,并且注释不可以嵌套,即下面的注释是不合法的:
/*Thisis/*avalid*/comment*/
程序流程图
程序的流程参照了书本TINY编译器的实例程序:
语法分析器(Parser)调用词法分析器得到符合词法的字,建立语法树;符号表通过对语法树的分析,建立符号表,同时检查变量未定义等错误;类型检查包括检查表达式两边是否匹配,函数参数是否匹配等等;经由上述步骤而未出错的源程序被认为是合法程序,然后代码生成通过语法树和符号表生成PCode中间代码,并将变量地址存入符号表。
其中类型检查和代码生成不要求实现。
本次实验要求分组,一组五人,一人完成一个部分。
本组实验分组成员以及分工介绍:
汪晨风:
(设计并实现cminus符号表);E02620105
蔡其星:
(编写cminus.l文件,并用lex工具生成c代码);E02620107
赵婷:
(设计cminus语法树结构);E02620106
马培良:
编写cminus.y文件,并用yacc工具生成可执行代码);E02620121
丘廷:
(进行程序的测试)
以下为具体实验分步报告以及过程:
第一部分:
设计cminus符号表
符号表是编译器中的主要继承属性,并且在语法树之后,形成了主要的数据结构。
符号表主要的操作有插入、查找和删除。
杂凑表(hash表)通常为符号表的实现提供了最好的选择,因为所有3种操作都能在几乎恒定的时间内完成,在实践中也是最常使用。
该课程设计所用的C-符号表采用建立杂凑表的方法。
杂凑表是一个入口数组,称作“桶(bucket)”,使用一个整数范围的索引,通常从0到表的尺寸减1。
杂凑函数(hashfuction)把索引键(在这种情况下是标识符名,组成一个字符串)转换成索引范围内的一个整数的杂凑值,对应于索引键的项存储在这个索引的“桶”中。
每个“桶”实际上又是一个线性表,通过把新的项插入到“桶”表中来解决冲突在任何情况下,“桶”数组的实际大小要选择一个素数,因为这将使一般的杂凑函数运行得更好。
杂凑函数。
在符号表实现中使用的杂凑函数将字符串(标识符名)转换成0...size-1范围内的一个整数。
一般这通过3步来进行。
首先,字符串中的每个字符转换成一个非负整数。
然后,这些整数用一定的方法组合形成一个整数。
最后,把结果整数调整到0...size-1范围内。
冲突的一个好的解决办法是,当加上下一个字符的值时,重复地使用一个常量作为乘
法因子。
因此,如果ci是第i个字符的数字值,hi是在第i步计算的部分杂凑值,那么hi根据下面的递归公式计算,h0=0,hi-1=ahi-ci,最后的杂凑值用h=hnmodsize计算。
这里n是杂凑的名字中字符的个数。
这等价于下列公式当然,在这个公式中a的选择对输出结果有重要影响。
a的一种合理的选择是2的幂,如16或128,这样乘法可以通过移位来完成。
该程序a选16,size取211。
由于在数据结构方面为了实现很方便的进行查找,插入,删除等操作。
我们把它的数据结构设计成一哈稀表结构,哈稀表的查找,插入等操作是飞快的。
我们所设计的哈稀结构符号表是参考教科书上P295
它的结构如下:
符号表的杂凑函数
#defineSIZE211
#defineSHIFT4
inthash(char*key)
{inttemp=0;
inti=0;
while(key[i]!
='\0')
{temp=((temp< ++i; } returntemp; } 该符号表完成了插入[voidst_insert(char*name,intlineno,intloc)]、查找[intst_lookup(char*name)]工作 源程序: symtab.c #include #include #include #include"symtab.h" /*定义哈稀表的最大值*/ #defineSIZE211 /*SHIFTisthepoweroftwousedasmultiplier inhashfunction*/ #defineSHIFT4 /*哈稀函数结构*/ staticinthash(char*key) {inttemp=0; inti=0; while(key[i]! ='\0') {temp=((temp< ++i; } returntemp; } typedefstructLineListRec {intlineno; structLineListRec*next; }*LineList; typedefstructBucketListRec {char*name; LineListlines; intmemloc;/*memorylocationforvariable*/ structBucketListRec*next; }*BucketList; /*哈稀表*/ staticBucketListhashTable[SIZE]; voidst_insert(char*name,intlineno,intloc) {inth=hash(name); BucketListl=hashTable[h]; while((l! =NULL)&&(strcmp(name,l->name)! =0)) l=l->next; if(l==NULL)/*variablenotyetintable*/ {l=(BucketList)malloc(sizeof(structBucketListRec)); l->name=name; l->lines=(LineList)malloc(sizeof(structLineListRec)); l->lines->lineno=lineno; l->memloc=loc; l->lines->next=NULL; l->next=hashTable[h]; hashTable[h]=l;} else/*foundintable,sojustaddlinenumber*/ {LineListt=l->lines; while(t->next! =NULL)t=t->next; t->next=(LineList)malloc(sizeof(structLineListRec)); t->next->lineno=lineno; t->next->next=NULL; } } intst_lookup(char*name) {inth=hash(name); BucketListl=hashTable[h]; while((l! =NULL)&&(strcmp(name,l->name)! =0)) l=l->next; if(l==NULL)return-1; elsereturnl->memloc; } voidprintSymTab(FILE*listing) {inti; fprintf(listing,"VariableNameLocationLineNumbers\n"); fprintf(listing,"---------------------------------\n"); for(i=0;i {if(hashTable[i]! =NULL) {BucketListl=hashTable[i]; while(l! =NULL) {LineListt=l->lines; fprintf(listing,"%-14s",l->name); fprintf(listing,"%-8d",l->memloc); while(t! =NULL) {fprintf(listing,"%4d",t->lineno); t=t->next; } fprintf(listing,"\n"); l=l->next; } } } }/*printSymTab*/ symtab.h #ifndef_SYMTAB_H_ #define_SYMTAB_H_ voidst_insert(char*name,intlineno,intloc);/*插入函数*/ intst_lookup(char*name);/*查找函数*/ voidprintSymTab(FILE*listing);/*用来打印哈稀表内容*/ #endif 符号表设计的好坏直接影响到整个程序运行的速度,效率以及准确度。 因为接下来的parse工作是基于符号表的,是从符号表里提取token进行语法分析的。 为了提高程序运行的的效率,我们把scan直接通过parse来调用。 具体的来讲就是,程序运行时,首先进入parse部分,当parse要用到token时,调用scan部分扫描原文件生成token储存在符号表中,并同时提供给parse进行语法分析。 这样就可以一遍完成整个原文件的扫描。 第二部分: 运用LEX实现cminus词法分析程序。 这一部比较关键,设计的正确与否直接影响到在scan过程中token的产生。 以及整个程序运行的结果的正确与否。 在这里主要定义cminus的基本语法规则,以及token类型,运算符类型,并且定义cminus关键字,便于在程序运行时能对其进行识别。 一下为cminus.l文件原代码: /*定义全局变量、函数及包含文件说明: */ %{ #include"globals.h" #include"util.h" #include"scan.h" #defineMAXTOKENLEN40 chartokenString[40]; intlineno=0; %} /*有关语法规则以及token的定义: */ digit[0-9] n
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 课程设计 实验 报告