您好,欢迎访问三七文档
《编译原理》实验报告软件131陈万全132852一、需求分析通过对一个常用高级程序设计语言的简单语言子集编译系统中词法分析、语法分析、语义处理模块的设计、开发,掌握实际编译系统的核心结构、工作流程及其实现技术,获得分析、设计、实现编译程序等方面的实际操作能力,增强设计、编写和调试程序的能力。通过开源编译器分析、编译过程可视化等扩展实验,促进学生增强复杂系统分析、设计和实现能力,鼓励学生创新意识和能力。实验项目实验内容1、词法分析程序设计与实现构造具有关键字、运算符、标识符、无符号常数等单词的词法分析程序。输入由符合及不符合规定单词类别结构的各类单词组成的源程序。输出单词串的二元式编码(CLASS,VALUE)。2、语法分析程序设计与实现将词法分析程序输出的单词串作为输入,针对常见的表达式、赋值语句、条件语句、循环语句等语法成分,选择有代表性的语法分析方法,如递归下降法、算符优先分析、LL(1)、LR等方法之一,设计实现相应的语法分析程序。3、语义分析程序设计与实现对各语法单位增加语义子程序,将表达式或可执行语句翻译为四元式序列输出,并能进行错误检查与处理,将错误信息输出。1、词法分析程序设计与实现假定一种高级程序设计语言中的单词主要包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符和四个算术运算符,试构造能识别这些单词的词法分析程序。输入:由符合和不符合所规定的单词类别结构的各类单词组成的源程序文件。输出:把所识别出的每一单词均按形如(CLASS,VALUE)的二元式形式输出,并将结果放到某个文件中。对于标识符和无符号常数,CLASS字段为相应的类别码的助记符;VALUE字段则是该标识符、常数的具体值;对于关键字和运算符,采用一词一类的编码形式,仅需在二元式的CLASS字段上放置相应单词的类别码的助记符,VALUE字段则为“空”。2、语法分析程序设计与实现选择对各种常见高级程序设计语言都较为通用的语法结构——算术表达式的一个简化子集——作为分析对象,根据如下描述其语法结构的BNF定义G2[算术表达式],任选一种学过的语法分析方法,针对运算对象为无符号常数和变量的四则运算,设计并实现一个语法分析程序。G2[算术表达式]:算术表达式→项|算术表达式+项|算术表达式-项项→因式|项*因式|项/因式因式→运算对象|(算术表达式)若将语法范畴算术表达式、项、因式和运算对象分别用E、T、F和i代表,则G2可写成:G2[E]:E→T|E+T|E-TT→F|T*F|T/FF→i|(E)输入:由实验一输出的单词串,例如:UCON,PL,UCON,MU,ID······输出:若输入源程序中的符号串是给定文法的句子,则输出“RIGHT”,并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必要的出错说明信息。3、语义分析程序设计与实现对文法G2[算术表达式]中的产生式添加语义处理子程序,完成运算对象是简单变量(标识符)和无符号数的四则运算的计值处理,将输入的四则运算转换为四元式形式的中间代码。输入:包含测试用例(由标识符、无符号数和+、−、*、/、(、)构成的算术表达式)的源程序文件。输出:将源程序转换为中间代码形式表示,并将中间代码序列输出到文件中。若源程序中有错误,应指出错误信息二、设计思路1、词法分析程序设计与实现1)单词分类为了编程的实现。我们假定要编译的语言中,全部关键字都是保留字,程序员不得将它们作为源程序中的标识符;作了这些限制以后,就可以把关键字和标识符的识别统一进行处理。即每当开始识别一个单词时,若扫视到的第一个字符为字母,则把后续输入的字母或数字字符依次进行拼接,直至扫视到非字母、数字字符为止,以期获得一个尽可能长的字母数字字符串,然后以此字符串查所谓保留字表(此保留字表要事先造好),若查到此字符串,则取出相应的类别码;反之,则表明该字符串应为一标识符。表1语言中的各类单词符号及其分类码表单词符号类别编码类别码的助记符单词值begin1BEGINend2ENDif3IFthen4THENelse5ELSE标识符6ID字母打头的字母数字串无符号常数7UCON机内二进制表示8LT=9LE=10EQ11NE12GT=13GE:=14IS+15PL-16MI*17MU/18DI2)词法分析器的设计函数GETCHAR:每调用一次,就把扫描指示器当前所指示的源程序字符送入字符变量ch,然后把扫描指示器前推一个字符位置。字符数组TOKEN:用来依次存放一个单词词文中的各个字符。函数CAT:每调用一次,就把当前ch中的字符拼接于TOKEN中所存字符串的右边。函数LOOKUP:每调用一次,就以TOKEN中的字符串查保留字表,若查到,就将相应关键字的类别码赋给整型变量c;否则将c置为零。函数RETRACT:每调用一次,就把扫描指示器回退一个字符位置(即退回多读的那个字符)。函数OUT:一般仅在进入终态时调用此函数,调用的形式为OUT(c,VAL)。图1识别表I所列语言中的部分单词的DFA及相关的语义过程3)词法分析程序的实现编写的扫描器:charTOKEN[20],TOKEND[20],TOKENDO[20];intlookup(char*);voidout(int,char*);voidreport_error(void);//externvoidLEX(void);intsiagn=0;//标志位FILE*fp1;char*KeyWordTable[MAX_KEY_NUMBER]={begin,end,if,then,else,KEY_WORD_END};/*查保留字表,判断是否为关键字*/intlookup(char*token){intn=0;while(strcmp(KeyWordTable[n],KEY_WORD_END))/*strcmp比较两串是否相同,若相同返回0*/{if(!strcmp(KeyWordTable[n],token))/*比较token所指向的关键字和保留字表中哪个关键字相符*/{returnn+1;/*根据单词分类码表I,设置正确的关键字类别码,并返回此类别码的值*/break;}n++;}return0;}voidscanner_example(FILE*fp){charch;inti,c,isd,cpoint;doubleo;ch=fgetc(fp);//fgetc函数在文件中读取一个字符if(isalpha(ch))/*itmustbeaidentifer!它必须是一个标识符判断字符ch是否为英文字母,若为小写字母,返回2,若为大写字母,返回1。若不是字母,返回0*/{TOKEN[0]=ch;ch=fgetc(fp);i=1;while(isalnum(ch)||ch=='.')//isalnum函数判断ch是否为空当ch为数字0-9或字母a-z及A-Z时,返回非零值,否则返回零{if(ch=='.'){cpoint=-1;//标志字符串中有小数点}TOKEN[i]=ch;i++;ch=fgetc(fp);}TOKEN[i]='\0';if(ch==''||ch==''||ch=='='||ch==':'){fseek(fp,-2,1);siagn=1;}elsefseek(fp,-1,1);//fseek(fp,-1,1);/*retractfseek函数每调用一次,就把扫描指示器回退一个字符位置(即退回多读的那个字符)*/i=0;if(TOKEN[i]=='o'||TOKEN[i]=='O'){i++;if(TOKEN[i]=='x'||TOKEN[i]=='X'){i++;while(TOKEN[i]!='\0'){if(!isdigit(TOKEN[i])||TOKEN[i]!='a'||TOKEN[i]!='b'||TOKEN[i]!='c'||TOKEN[i]!='d'||TOKEN[i]!='e'||TOKEN[i]!='f'||TOKEN[i]!='A'||TOKEN[i]!='B'||TOKEN[i]!='C'||TOKEN[i]!='D'||TOKEN[i]!='E'||TOKEN[i]!='F'||TOKEN[i]!='.'){isd=-1;}isd=16;//标志字符串十六进制i++;}}elseif(TOKEN[i]=='0'||TOKEN[i]=='1'||TOKEN[i]=='2'||TOKEN[i]=='3'||TOKEN[i]=='4'||TOKEN[i]=='5'||TOKEN[i]=='6'||TOKEN[i]=='7'||TOKEN[i]=='.'){isd=8;//标志字符串八进制i++;while(TOKEN[i]!='\0'){if(TOKEN[i]!='0'||TOKEN[i]!='1'||TOKEN[i]!='2'||TOKEN[i]!='3'||TOKEN[i]!='4'||TOKEN[i]!='5'||TOKEN[i]!='6'||TOKEN[i]!='7'||TOKEN[i]!='.'){isd=-1;}isd=8;i++;}}}if(isd==8){strncpy(TOKEND,TOKEN+1,strlen(TOKEN)-1);//拷贝函数//printf(%o,atof(TOKEND));o=octal(TOKEND);//printf(%g,o);sprintf(TOKENDO,%g,octal(TOKEND));out(OCTAL,TOKENDO);}elseif(isd==16){strncpy(TOKEND,TOKEN+2,strlen(TOKEN)-2);//拷贝函数o=octal(TOKEND);//printf(%g,o);sprintf(TOKENDO,%g,hex(TOKEND));out(HEX,TOKENDO);}else{if(cpoint==-1)report_error();//当字符串中有小数点时,为错误else{c=lookup(TOKEN);//looup查询函数查找保留字if(c==0)out(ID,TOKEN);elseout(c,);//out函数输出功能}}}elseif(isdigit(ch))//isdigit函数检查参数c是否为阿拉伯数字0到9。{/*TOKEN[0]=ch;ch=fgetc(fp);i=1;while(isdigit(ch)||ch=='-'||ch=='E'||ch=='e'||ch=='.'){TOKEN[i]=ch;i++;ch=fgetc(fp);}TOKEN[i]='\0';*/intClass;fseek(fp,-1,1);Class=LEX(fp);if(Class==1){charpi[30]=;itoa(ICON,pi,10);out(INT,pi);}elseif(Class==2){charpd[30]=;sprintf(pd,%g,FCON);out(DOUBLE,pd);}elsereport_error();//fseek(fp,-1,1);if(chf==''||chf==''||chf=='='||chf==':'||chf=='+'||chf=='-'||chf=='*'||chf=='/'){fseek(fp,-2,1);siagn=1;}else{fseek(fp,-1,1);siagn=1;}}elseswitch(ch){case'':ch=fgetc(fp);if(ch=='='){ch=fgetc(fp);if(isalnum(ch))fseek(fp,-2,1);elsefseek(fp,-1,1);//如果符号后面不是空值则退后一步保证符号后可以直接跟数字也可以跟空格
本文标题:编译原理实验报告
链接地址:https://www.777doc.com/doc-2068904 .html