中间代码生成实验报告

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

/* 判断ch是不是数字 */
int jstr(char ch){ /* 判断ch是不是字母或数字 */ if(strchr(strstring,ch)==0) return 0; else return 1; } void advance() { getnbc(); kind=0; if (jchar(ch)==1) {
三 、 测试程序
ff:=6+6*6-; if sl>89+56*67 then f:=7*7+4; ff:=6+6*6-6%4+8; if sl+78*76>89*56+67 then while a-7>98+45*45 do f:=7*7+4;
. 四 、 运行结果
首先对测试程序进行语法分析,识别出正确 的句子,当识别出正确的句子时,就对当前句 子进行语义分析,而语法不正确的句子不进行 语义分析。
case 8:{printf(" Error(8):Except 'then' \n");break;} case 9:{printf(" Error(9):Except Condition Expression\n ");break;} case 10:{printf(" Error(10):Except 'do' ");break;} default: ; } }
char tx[10]; char tn[4],signt1[20],signt2[20],ju[20]; int cc,ii,k,num,kind,t,e4=0,e3=0,judge=1,row1=0; int startc,idsh=0,opsh=0,tt=1,nn=1,signwh,over=0,adds=0,whs=0,pp=0; int li=0; char filename[15]; FILE *fp;
#include<string.h> #include<stdio.h> #include<stdlib.h> #define reser 20 char *charstring="abcdefghijklmnopqrstuvwxyz"; char *numstring="0123456789"; char *strstring="abcdefghijklmnopqrstuvwxyz0123456789"; char reserve[reser][10]; char idshed[40][10],opshed[40][10]; char token[15],id[15],sym[15]; char line[80],tempp[240]; char ch,ch1,temp,tem;
五 、 实验小结
终于完成了编译原理的三次实验,这几次实验使 我们更彻底地巩固了编译原理。从詷法分析到语法 分析直到这次的中间代码都是看似简单的基础知 识,却花了不少时间对课本多次反复研究、请教学 习,进行深层次地探讨才找出编程时出现的种种问 题。还有很多程序方面很细节的问题,很容易被突 略,却往往又是关键。 总地来说,虽然实验做得很辛苦,但真的可以从 实验当中学习到很多,认识到很多。并对编译理解 也透彻了许多,比较清晰地掌握了编译程序的原理 和方法。 附录:
k=0; do { if(k<15) { token[k]=ch; k++;} getch(); } while(jstr(ch)==1); if (li==0) retract(); else ret(); token[k]='\0'; /*截去token中的无用字符*/
strcpy(id,token); for(t =0;t<=20;t++) {if(strcmp(reserve[t],id)==0) break;} if ( t<=20 ) kind=t ; else kind=21; strcpy(sym,id); } else if (jnum(ch)==1) { k=0; do{ if ( k<15 ) { token[k]=ch; k++;} getch(); } while( jstr(ch)==1);
void e(){ advance(); if((strcmp(sym,"+")==0)||(strcmp(sym,"-")==0)|| (strcmp(sym,"*")==0)||(strcmp(sym,"%")==0)) { printf("%s",sym); advance(); if((kind==21) || (kind==22)){ /* kind为21,22分别表示的是标志 符和数字 */ printf("%s",sym); e();} else { e4=1 ;error(4);} } /*出错退出,e4=1*/ } void c(){ advance(); if((kind==21) || (kind==22)){ printf("%s",sym); e(); if(e4==1); /*e4的作用是判断程序从e()中是不是出错 退出*/
ff:=6+6*6- Error(4):Except ID or NUM ; Error(2):Syntax error if sl>89+56*67 then f:=7*7+4; success!!! (1) [ *, 56, 67, T1 ] (2) [ +, 89, T1, T2 ] (3) [j>, sl, T2, (4) ] (4) [ *, 7, 7, T3 ] (5) [ +, T3, 4, T4 ] (6) [ :=, T4, -, f ] ff:=6+6*6-6%4+8; success!!! (7) [ *, 6, 6, T5 ] (8) [ +, 6, T5, T6 ] (9) [ %, 6, 4, T7 ] (10) [ -, T6, T7, T8 ] (11) [ +, T8, 8, T9 ] (12) [ :=, T9, -, ff ] if sl+78*76>89*56+67 then while a-7>98+45*45 do f:=7*7+4; success!!! (13) [ *, 78, 76, T10 ] (14) [ +, sl,T10, T11 ] (15) [ *, 89, 56, T12 ] (16) [ +,T12, 67, T13 ] (17) [j>, T11, T13, (18) ] (18) [ -, a, 7, T14 ] (19) [ *, 45, 45, T15 ] (20) [ +, 98,T15, T16 ] (21) [j>, T14, T16, (22) ] (22) [ *, 7, 7, T17 ] (23) [ +,T17, 4, T18 ] (24) [ :=, T18, -, f ] (25) [j, _, _, (18)] . Error(2):Syntax error
if (li==0) retract(); else ret(); kind=22; token[k]='\0'; strcpy(sym,token); } else { if(ch=='.') kind=26; k=0; do{ sym[k]=' '; k++; }while(k!=15); sym[0]=ch; sym[1]='\0'; } } void error(int n){ judge=0; /*出错退出,将judge=0*/ switch(n){ case 0:{printf(" Error(0):Expect ':' \n"); break;} case 1:{printf(" Error(1):Expect '=' \n"); break;} case 2:{printf(" Error(2):Syntax error \n");break;} case 3:{printf(" Error(3):Except Operater \n");break;} case 4:{printf(" Error(4):Except ID or NUM \n");break;} case 5:{printf(" Error(5):Except ';' \n");break;} case 6:{printf(" Error(6):Except '<' or '>'\n");break;} case 7:{printf(" Error(7):Except '=' \n" );break;}
void getch(){ if(li==0) { if (cc==ii){ cc=1; ii=0; if (row1==1) fseek(fp,-1,1); 整个文本的开头,则不需要*/ line[0]=fgetc(fp); row1=1; /*读行首字符将指针退回一格,若是
while(((temp=fgetc(fp))!='\n') && (temp!=EOF)) { line[cc]=temp; cc++; tempp[pp]=temp; pp++; } line[cc]=' '; /*将缓冲带后加上一个空字符,以便行和行之间 号区分 */ cc++; tempp[pp]=' ';
pp++; while(((temp=fgetc(fp))=='\n') && (temp!=EOF)); /* 跳过空 行*/ line[cc]='\0'; } tem=line[ii]; ii++; ch=tem; } else{ ch=tempp[pp]; pp++; } } void getnbc(){ getch(); while (ch==' ') getch(); if (ch=='{') { do {getch();} while( ch=='}'); getnbc(); } } void retract(){ ii--;
一条无条件转向四元式,重新转到条件判断 式C的第一条四元式。当要产生无条件转向 四元式时,它的转向目标C的第一条四元式 已经产生了,所以具体的做起来是不太困难 的。只要记下当前while中的C的第一条四元 式的位置,填上就可以了。 整个程序的结束是当读入“ . ”时,程序 就中止。 程序中还有很多细节问题,具体的可以后面的 附录:程序的完整代码。
术表达式E的四元式。程序中的ec函数的功 能就是产生算术表达式的四元式,在ec函数 中使用了两个栈idshed,opshed,分别是 算术表达式的数据栈和符号栈。每次提取一 个数字和一个算符,然后将算符与与栈顶算 符进行优先级比较,优先级高则将单前数字 和算符进栈,低或者相等的话则将当前栈顶 元素进行合并,产生四元式。直至整个算术 表达式结束。其中还有一些细节百度文库题,具体 的做法可以参看程序。 对于实验给定的if语句的文法格式,条件判 断式C只中可能是>或者<=两种关系,不可能 是布尔表达式,这样程序就简单的多了。 通过ec函数可以产生条件判断式C中的E的四 元式,然后只要加上转向四元式就可以了。 本实验程序中只给出真出口的转向四元式, 没有给出假出口的转向四元式,这在实际中 是不可以的,但在本实验中,实际上是对每 条独立的语句进行语法分析,给出假出口转 向四元式实际上意义不大,而且假出口转向 语句的转移目标必须要到整个语句分析结束 以后才可以知道,这样就要建立栈,然后回 填,这样会使程序复杂很多,所以没有加上 假出口转向四元式。 对于while语句,具体的做法和if语句差不 多,所不同的是当while语句结束时,要多出
一 、 实验目的
通过在实验二的基础上,增加中间代码生成部 分,使程序能够 对实验二中的识别出的赋值语句,if语句和 while语句进行语义分析,生成四元式中间代 码。
二 、 实验方法
实验程序由c语言完成,在Turboc 2.0环境中调 试通过。 语义分析程序的基本做法是对文法中的每 个产生式分别编写一个语义分析子程序,当 程序语法部分进行推倒或规约时,就分别调 用各自的语义分析程序。当语法分析结束 时,语义分析也就结束了。 在本实验程序中,当语法分析部分识别出 语法正确的句子时,就进入content函数 (当语法分析识别出不正确的句子时,不进 入content函数,也就是不进行语义分 析),然后根据句子的类型进行分类,进入 不同的语义处理部分。 对于赋值语句,关键是产生正确的处理算
} void ret(){ pp--; } int jchar(char ch){ if(strchr(charstring,ch)==0) return 0; else return 1; } int jnum(char ch){ if(strchr(numstring,ch)==0) return 0; else return 1; } /* 判断ch是不是字母 */
相关文档
最新文档