您好,欢迎访问三七文档
编译原理实验报告第1页共30页实验一词法分析一、实验目的编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。二、实验题目如源程序为C语言。输入如下一段:main(){inta=-5,b=4,j;if(a=b)j=a-b;elsej=b-a;}要求输出如下:(2,”main”)(5,”(”)(5,”)”)(5,”{”)(1,”int”)(2,”a”)(4,”=”)(3,”-5”)(5,”,”)(2,”b”)(4,”=”)(3,”4”)(5,”,”)(2,”j”)(5,”;”)(1,”if”)(5,”(”)(2,”a”)(4,”=”)(2,”b”)(5,”)”)(2,”j”)(4,”=”)(2,”a”)(4,”-”)(2,”b”)(5,”;”)(1,”else”)(2,”j”)(4,”=”)(2,”b”)(4,”-”)(2,”a”)(5,”;”)(5,”}”)三、实验理论依据(一)识别各种单词符号程序语言的单词符号一般分为五种:编译原理实验报告第2页共30页关键字(保留字/基本字)if、while、begin…标识符:常量名、变量名…常数:34、56.78、true、‘a’、…运算符:+、-、*、/、〈、and、or、….界限符:,;(){}/*…识别单词:掌握单词的构成规则很重要标识符的识别:字母|下划线+(字母/数字/下划线)关键字的识别:与标识符相同,最后查表常数的识别界符和算符的识别大多数程序设计语言的单词符号都可以用转换图来识别,如图1-1图1-1词法分析器输出的单词符号常常表示为二元式:(单词种别,单词符号的属性值)单词种别通常用整数编码,如1代表关键字,2代表标识符等编译原理实验报告第3页共30页关键字可视其全体为一种,也可以一字一种。采用一字一种得分法实际处理起来较为方便。标识符一般统归为一种常数按类型(整、实、布尔等)分种运算符可采用一符一种的方法。界符一般一符一种的分法。(二)超前搜索方法词法分析时,常常会用到超前搜索方法。如当前待分析字符串为“a+”,当前字符为“”,此时,分析器倒底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。于是分析器读入下一个字符’+’,这时可知应将’’解释为大于运算符。但此时,超前读了一个字符’+’,所以要回退一个字符,词法分析器才能正常运行。又比如:‘+’分析为正号还是加法符号(三)预处理预处理工作包括对空白符、跳格符、回车符和换行符等编辑性字符的处理,及删除注解等。由一个预处理子程序来完成。四、词法分析器的设计1、设计方法:2、写出该语言的词法规则。3、把词法规则转换为相应的状态转换图。4、把各转换图的初态连在一起,构成识别该语言的自动机5、设计扫描器6、把扫描器作为语法分析的一个过程,当语法分析需要一个单词时,就调用扫描器。7、扫描器从初态出发,当识别一个单词后便进入终态,送出二元式编译原理实验报告第4页共30页图1-2取单词程序框图五、程序代码开始读标识符是字母掠过空格和回车符查保留字表是否查到换成属性字结束是数字是特殊符号error取数换成属性字换成属性字换成属性字YNYYYNNN编译原理实验报告第5页共30页#includestdio.h#includestring.hFILE*fp;charcbuffer;char*key[8]={if,else,for,while,do,return,break,continue};intatype,id=4;intisalpha(charc){if((c='z')&&(c='a')||(c='Z')&&(c='A'))return1;elsereturn0;}intisdigit(charc){if(c='0'&&c='9')return1;elsereturn0;}intsearch(charsearchchar[],intwordtype)/*判断单词是保留字还是标识符*/{inti=0;intp;switch(wordtype){case1:for(i=0;i=7;i++){if(strcmp(key[i],searchchar)==0){p=i+1;break;}/*是保留字则p为非0且不重复的整数*/elsep=0;/*不是保留字则用于返回的p=0*/}return(p);}}charalphaprocess(charbuffer){intatype;/*保留字数组中的位置*/inti=-1;charalphatp[20];while((isalpha(buffer))||(isdigit(buffer))||buffer=='_'){alphatp[++i]=buffer;buffer=fgetc(fp);}/*读一个完整的单词放入alphatp数组中*/alphatp[i+1]='\0';atype=search(alphatp,1);/*对此单词调用search函数判断类型*/if(atype!=0){printf((%d,\%s\)\n,atype-1,alphatp);id=1;}else编译原理实验报告第6页共30页{printf((2,\%s\)\n,alphatp);id=2;}return(buffer);}chardigitprocess(charbuffer){inti=-1;chardigittp[20];while((isdigit(buffer))||buffer=='.')/*1判断小数*/{digittp[++i]=buffer;buffer=fgetc(fp);}digittp[i+1]='\0';printf((3,\%s\)\n,digittp);id=3;return(buffer);}charotherprocess(charbuffer){charch[20];ch[0]=buffer;ch[1]='\0';if(ch[0]==','||ch[0]==';'||ch[0]=='{'||ch[0]=='}'||ch[0]=='('||ch[0]==')'){printf((5,\%s\)\n,ch);buffer=fgetc(fp);id=5;return(buffer);}if(ch[0]=='/'){buffer=fgetc(fp);if(buffer=='*')/*2区分注释符号和除号*/{ch[1]=buffer;buffer=fgetc(fp);while(buffer!='*'){buffer=fgetc(fp);}ch[2]=buffer;buffer=fgetc(fp);if(buffer=='/'){ch[3]=buffer;ch[4]='\0';}printf((5,\%s\)\n,ch);}编译原理实验报告第7页共30页else{printf((4,\%s\)\n,ch);id=4;return(buffer);}buffer=fgetc(fp);id=5;return(buffer);}if(ch[0]=='*'){printf((4,\%s\)\n,ch);buffer=fgetc(fp);id=4;return(buffer);}if(ch[0]=='='||ch[0]=='!'||ch[0]==''||ch[0]==''){buffer=fgetc(fp);if(buffer=='='){ch[1]=buffer;ch[2]='\0';printf((4,\%s\)\n,ch);}else{printf((4,\%s\)\n,ch);id=4;return(buffer);}buffer=fgetc(fp);id=4;return(buffer);}if(ch[0]=='+'||ch[0]=='-'){if(id==4)/*在当前符号以前是运算符,则此时为正负号*/{buffer=fgetc(fp);ch[1]=buffer;ch[2]='\0';printf((3,\%s\)\n,ch);id=3;buffer=fgetc(fp);return(buffer);}ch[1]='\0';printf((4,\%s\)\n,ch);buffer=fgetc(fp);id=4;return(buffer);}if(ch[0]=='#')/*3识别头文件*/编译原理实验报告第8页共30页{chart[20];inti=0;t[0]=ch[0];buffer=fgetc(fp);while((isalpha(buffer))||buffer==''||buffer==''||buffer==''){t[++i]=buffer;buffer=fgetc(fp);}t[i+1]='\0';printf((6,\%s\)\n,t);id=6;return(buffer);}if(ch[0]=='\\')/*4识别转义符号*/{buffer=fgetc(fp);ch[1]=buffer;printf((6,\%s\)\n,ch);buffer=fgetc(fp);return(buffer);}if(ch[0]=='|'||ch[0]=='&')/*5判断或与*/{buffer=fgetc(fp);if(ch[0]==buffer){ch[1]=buffer;}ch[2]='\0';printf((4,\%s\)\n,ch);buffer=fgetc(fp);return(buffer);}if(ch[0]==''||ch[0]=='\'')/*6判断双引号和单引号*/{printf((5,\%s\)\n,ch);id=5;buffer=fgetc(fp);return(buffer);}}intmain(){if((fp=fopen(example.c,r))==NULL)/*只读方式打开一个文件*/编译原理实验报告第9页共30页printf(error);else{cbuffer=fgetc(fp);/*fgetc()函数:从磁盘文件读取一个字符*/while(cbuffer!=EOF){if(cbuffer==''||cbuffer=='\n')/*掠过空格和回车符*/cbuffer=fgetc(fp);elseif(isalpha(cbuffer))cbuffer=alphaprocess(cbuffer);elseif(isdigit(cbuffer))cbuffer=digitprocess(cbuffer);elsecbuffer=otherprocess(cbuffer);}}return0;}六、实验结果程序添加了识别小数,识别注释符,识别自加自减符号,识别头文件,识别转义符号,识别或与符号,识别单引号和双引号,识别中括号,识别格式符,结果如图1-3所示:编译原理实验报告第10页共30页图1-3编译原理实验报告第11页共30页实验二LL(1)分析法一、实验目的:根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。本次实验的目的主要是加深对预测分析LL(1)分析法的理解。二、实验题目实验规定对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E::=TG(2)G::=+TG(3)G::=ε(4)T::=FS(5)S::=*FS(6)S::=ε(7)F::=(E)(8)F::=i若输入串为i+i*i#,则输出为:LL(1)的分析表为:i+*()#说明EeeSelect(E→TG)={(,i}#Ei+i*i##GTi+i*i##GSFi+i*i##GSii+i*i##GS+i*i##G+i*i##GT++i*i#…………T→FS2……….…+7G→+TG6S→є5i4F→i3E→TG1产生式剩余串分析栈步骤编译原理实验报告第12页共30页Ggg1g1Select(G→+TG)={+}Select(G→є)={#,
本文标题:编译原理实验
链接地址:https://www.777doc.com/doc-6019028 .html