《河工大版编译原理实验报告.doc》由会员分享,可在线阅读,更多相关《河工大版编译原理实验报告.doc(24页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、编译原理实验报告学院: 国际教育学院 专业: 中法计算机合作专业 班级: 中法计122 姓名: 徐彤坤 学号: 目录实验一 词法分析程序实现3实验设计:3实验步骤3基本思路:6程序代码:6实验结果分析:13自我评鉴14实验二 语法分析程序实现15实验设计:15实验步骤15基本思路15程序代码17实验结果分析23实验一 词法分析程序实现实验设计:实验目的与要求通过编写和调试一个词法分析程序,掌握在对程序设计语言的源程序进行扫描的过程中,将字符流形式的源程序转化为一个由各类单词符号组成的流的词法分析方法。基本实验题目题目:试用手工编码方式构造识别以下给定单词的某一语言的词法分析程序。语言中具有的单
2、词包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符和四个算术运算符。实验步骤单词的分类:构造上述语言中的各类单词符号及其分类码表。单词符号类别编码类别码的助记符单词值begin1BEGINend2ENDif3IFthen4THENelse5ELSE标识符6ID字母打头的字母数字串无符号常数7UCON机内二进制表示8LT=9LE=10EQ11NE12GT=13GE:=14IS+15PL-16MI*17MU/18DI表I 语言中的各类单词符号及其分类码表图I 识别表I所列语言中的部分单词的DFA及相关的语义过程图I中所出现的语义变量及语义函
3、数的含义和功能说明如下: 函数GETCHAR:每调用一次,就把扫描指示器当前所指示的源程序字符送入字符变量ch,然后把扫描指示器前推一个字符位置。 字符数组TOKEN:用来依次存放一个单词词文中的各个字符。 函数CAT:每调用一次,就把当前ch中的字符拼接于TOKEN中所存字符串的右边。 函数LOOKUP:每调用一次,就以TOKEN中的字符串查保留字表,若查到,就将相应关键字的类别码赋给整型变量c;否则将c置为零。函数RETRACT:每调用一次,就把扫描指示器回退一个字符位置(即退回多读的那个字符)。 函数OUT:一般仅在进入终态时调用此函数,调用的形式为OUT(c,VAL)。其中,实参c为相
4、应单词的类别码或其助记符;实参VAL为TOKEN(即词文)或为空串。函数OUT的功能是,在送出一个单词的内部表示之后,返回到调用该词法分析程序的那个程序。需要将程序一中的整常数扩展为无符号常数,以满足题目的要求。描述无符号数的右线性文法G1如下:无符号数 d余留无符号数无符号数 小数部分无符号数 d余留无符号数 d余留无符号数余留无符号数 十进小数余留无符号数 E指数部分余留无符号数 d余留无符号数 十进小数 E指数部分十进小数 d十进小数十进小数 d小数部分 d十进小数小数部分 d指数部分 d余留整指数指数部分 +整指数指数部分 -整指数指数部分 d整指数 d余留整指数整指数 d余留整指数
5、d余留整指数余留整指数 d图II所示为上述文法的状态转换图,其中编号0、1、2、6分别代表非终结符号、及。图II 文法G1的状态转换图表II 包含语义处理过程的识别无符号数的状态矩阵基本思路:程序代码:#include #include # include # include # include #define MAX_KEY_NUMBER 20#define KEY_WORD_END waiting for your expanding# define ID 6# define INT 7# define LT 8# define LE 9# define EQ 10# define NE
6、11# define GT 12# define GE 13# define IS 14# define PL 15# define MI 16# define MU 17# define DI 18# define UCON 19char TOKEN20; int lookup(char*); void out(int, char*); void report_error();void scanner_example(FILE *fp)char ch; int i, c; ch = fgetc(fp); int checkdot=0; int checke=0; int t; t=fgetc
7、(fp); fseek (fp,-1,1); while (t != EOF) if (isalpha(ch) /*it must be a identifer!*/TOKEN0 = ch; ch = fgetc(fp); i = 1;while (isalnum(ch)TOKENi = ch; i+;ch = fgetc(fp);TOKENi = 0;fseek(fp, -1, 1); /* retract*/c = lookup(TOKEN);if (c = 0) out(ID, TOKEN); else out(c, );else/*if (isdigit(ch)TOKEN0 = ch;
8、 ch = fgetc(fp); i = 1;while (isdigit(ch)TOKENi = ch; i+;ch = fgetc(fp);TOKENi = 0;fseek(fp, -1, 1);out(INT, TOKEN);else*/ if(isdigit(ch)/09 return true;/各种数 TOKEN0=ch; ch=fgetc(fp); i=1; while(isdigit(ch)|ch = . | ch = E|ch = e) /e的指数 小数 if (ch = .)checkdot =1; else if (ch = e|ch = E) checke = 1; T
9、OKENi=ch; i+; ch=fgetc(fp); if(ch = +)TOKENi=ch; i+; ch=fgetc(fp); TOKENi=ch; i+; ch=fgetc(fp); continue; else TOKENi=ch; i+; ch=fgetc(fp); TOKENi=ch; i+; ch=fgetc(fp); continue; /*if (ch = -)TOKENi=ch; i+; ch=fgetc(fp); TOKENi=ch; i+; ch=fgetc(fp); continue; */ TOKENi=ch; i+; ch=fgetc(fp); TOKENi=
10、0; fseek(fp,-1,1); if(checkdot=1) out(UCON,TOKEN); else if (checke = 1) out(UCON,TOKEN);/二进制数 else out(INT,TOKEN);/整型 elseswitch (ch) /输出case ) out(NE, );elsefseek(fp, -1, 1);TOKENi=ch; i+; ch=fgetc(fp);out(LT, );break;case =: out(EQ, ); break; case : ch = fgetc(fp); if (ch = =)out(IS, ); else fseek
11、(fp,-1,1); report_error( ); break;case : ch = fgetc(fp);if (ch = =)out(GE, );elsefseek(fp, -1, 1);out(GT, );break; case +:out(PL, );break; case -:out(MI, );break;case *:out(MU, );break;case /:out(DI, );break;case n: break;/ fseek(fp, -1, 1);report_enter(); break; /case r :out(ENT,n);break;case : bre
12、ak;case t: break;default: report_error(); break;ch=fgetc(fp); t=fgetc(fp);fseek (fp,-1,1);return;char *KeyWordTableMAX_KEY_NUMBER = begin, end, if, then, else, KEY_WORD_END ;/关键字int lookup(char *token)int n = 0;while (strcmp(KeyWordTablen, KEY_WORD_END) /*strcmp比较两串是否相同,若相同返回0*/if (!strcmp(KeyWordTa
13、blen, token) /*比较token所指向的关键字和保留字表中哪个关键字相符*/return n + 1; /*根据单词分类码表I,设置正确的关键字类别码,并返回此类别码的值*/break;n+;return 0; /*单词不是关键字,而是标识符*/void report_error()printf(error);void out(int c, char* v)char* cl = ;switch (c)case 1:cl = BEGIN; break;case2:cl = END; break;case3:cl = IF; break;case 4:cl = THEN; break;
14、case5:cl = ELSE; break;case6:cl = ID; break;case 7:cl = INT; break;case8:cl = LT; break;case9:cl = LE; break;case10: cl = EQ; break;case11: cl = NE; break;case 12:cl = GT; break;case13:cl = GE; break;case14:cl = IS; break;case15: cl = PL; break;case16: cl = MI; break;case17:cl = MU; break;case18: cl
15、 = DI; break; case19: cl = UCON; break;printf(%s,%s)n,cl, v);/输出int main(void) char *fname=file.txt; FILE *fp; if(fp=fopen(fname,r)=NULL) printf(Error!-Cant open file.); getchar(); exit(1); else scanner_example(fp); fclose(fp); return 1; 实验结果分析:建立一个名为file.txt的文件,键入“if myid=1.5E-2+100 then x:=y”并保存,运
16、行得到如下结果:结果:自我评鉴 词法分析的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。通过本试验的完成,更加加深了对词法分析原理的理解。在实验过程中开始不能实现指数部分的识别,但在老师的悉心指导下我经过更改可以成功识别了指数。由于我的编程功底并不是很好,并不能很好的实现要求中的所有功能,但我已经尽力去使自己的程序符合题目要求。实验二 语法分析程序实现实验设计:实验目的与要求通过设计、编制、调试一个典型的语法分析程序(任选一种有代表性的语法分析方法,如算符优先法、递归下降法、LL(1)、SLR(1)、LR(1
17、)等,作为编制语法分析程序的依据),对扫描器所提供的单词序列进行语法检查和结构分析,实现并进一步掌握常用的语法分析方法。实验内容选择对各种常见高级程序设计语言都较为通用的语法结构作为分析对象,给出其文法描述(注意应与所采用的语法分析方法比较贴近),设计并实现一个完整的语法分析程序(分析过程可暂不嵌入任何语义动作)。题目:对算术表达式的一个简化子集,根据如下其语法结构的BNF定义G2,任选学过的一种语法分析方法,针对运算对象为无符号数(和变量)的四则运算,编制一个语法分析程序。G2: | + | - | * | / | ()若将语法范畴、和分别用E、T、F和i代表,则G2可写成:ET|E+T|E
18、-T TF|T*F|T/F Fi|(E)实验步骤基本思路对以下文法进行语法分析:E-E+T|TT-T*F|FF-(E)|i实验采用文法:前后文无关文法 SLR(1) 分析表:产生式编号:0 E-E 1 E-E+T 2 E-E-T 3 E-T 4 T-T*F 5 T-T/F 6 T-F 7 F-(E) 8 F-i基本项目:E-E项目集:I0:E-E E-E+T E-E-T E-T T-T*F T-T/F T-F F-(E) F-iI1:GOTO(I0,E)E-E E-E+T E-E-TI2:GOTO(I0,T)E-T T-T*F T-T/FI3:GOTO(I0,F) T-FI4:GOTO(I0,
19、()F-(E) E-E+T E-E-T E-T T-T*F T-T/F T-F F-(E) F-iI5:GOTO(I0,i) F-iI6:GOTO(I1,+)E-E+T T-T*F T-T/F T-F F-(E) F-iI7:GOTO(I1,-)E-E-T T-T*F T-T/F T-F F-(E) F-iI8:GOTO(I2,*)T-T*F F-(E) F-iI9:GOTO(I2,/)T-T/F F-(E) F-iI10:GOTO(I4,E)F-(E) E-E+T E-E-TI11:GOTO(I6,T)E-E+T T-T*F T-T/FI12:GOTO(I7,T)E-E-T T-T*F T-
20、T/FI13:GOTO(I8,F) T-T*FI14:GOTO(I9,F) T-T/FI15:GOTO(I10,) F-(E)实验设计流程:程序代码#include #include #include #include# include #include# define BEGIN 1# define END 2# define IF 3# define THEN 4# define ELSE 5# define ID 6# define UCON 7# define LT 8# define LE 9# define EQ 10# define NE 11# define GT 12# de
21、fine GE 13# define IS 14# define PL 15# define MI 16# define MU 17# define DI 18 /以下是函数声明int CheckKeyword(char*);void ReadIn(void);void Print(int,char*);void CheckExperience(int*);int main(void) ReadIn(); return 0;void GetChars(char* str) int i=0,num10=0,0,0,0,0,0,0,0,0,0; int result=0; int j=0; cha
22、r retstrstrlen(str); memset(retstr,0,strlen(str); do / for(i=j;istrlen(str);i+) if(strj=0) break; else if(isalpha(strj) /对字母开头的标识符和关键字的检测 char newstrstrlen(str); memset(newstr,0,strlen(str); int s=0; for(int t=j;t50;t+) if(!isalnum(strt)&(!isalpha(strt)&(strt!= )/如果出现了不是数字和字母的字符,记录位置作为下个字符串的开始,跳出 j=
23、t; break; else if(strt= ) j=t+1; break; newstrs=strt; s+; newstrs+=0; result=CheckKeyword(newstr); strcpy(retstr,newstr); else if(strj= ) j+; continue; else if(isalnum(strj)/首字母是数字 double num; int check=0; char str150,str250; char newstrstrlen(str); memset(newstr,0,strlen(str); int s=0,r=0; for(int
24、t=j;t50;t+) if(strt=E) check=1; break; if(check=1) for(int t=j;t50;t+) if(strt=E) j=t+2; break; str1s=strt; s+; str1s+=0; char rem=strj-1; for(int t=j;t50;t+) if(!(isalnum(strt) j=t; break; str2r=strt; r+; str2r+=0; double num1=atof(str1); float num2=atof(str2); if(rem=+) num=num1*pow(10,num2); else
25、 num=num1/pow(10,num2); else for(int t=j;t50;t+) if(!(isalnum(strt)|(strt=.)|(strt=E)|(strt= ) j=t; break; newstrs=strt; s+; newstrs+=0; num=atof(newstr); char str20; sprintf(str,%g,num); strcpy(retstr,str); result=7; else if(strj=) result=11; j=j+2; else result=8; j+; else if(strj=) result=10; j=j+1; else if(strj=) if(isalnum(strj+1)|isalpha(strj+1) result=12; j=j+1; else if(strj+1=) result=13; j=j+2; else if(strj=:)&(strj+1=) result=14; j=j+2; else if(strj=+) result=15; j=j+1; else if(strj=-) result=16; j=j+1; else if(strj=*)
限制150内