中间代码基本块划分
编译原理第十一章解析

26
此处要用到的有向图,是一种其结点带有下述标记或附 加信息的DAG: ① 图的叶结点,即无后继的结点,以一标识符(变 量名)或常数作为标记,表示这个结点代表该变量或常数 的值。如果叶结点用来代表某变量A的地址,则用addr (A)作为这个结点的标记。通常把叶结点上作为标记的 标识符加上下标0,以表示它是该变量的初值。 ② 图的内部结点,即有后继的结点,以一运算符作为 标记,表示这个结点代表应用该运算符对其后继结点所代 表的值进行运算的结果。 ③ 图中各个结点上可能附加一个或多个标识符,表 示这些变量具有该结点所代表的值。
30
下面是仅含0,1,2型四元式的基本块的DAG构造算法。
首先,DAG为空。 对基本块的每一四元式,依次执行: 1. 如果NODE(B)无定义,则构造一标记为B的叶结点并定 义NODE(B)为这个结点; 如果当前四元式是0型,则记NODE(B)的值为n,转4。 如果当前四元式是1型,则转2.(1)。 如果当前四元式是2型,则:(Ⅰ)如果NODE(C)无定义, 则构造一标记为C的叶结点并定义NODE(C)为这个结点,(Ⅱ) 转2.(2)。 2. (1) 如果NODE(B)是标记为常数的叶结点,则转2.(3), 否则转3.(1)。 (2) 如果NODE(B)和NODE(C)都是标记为常数的叶结 点,则转2.(4),否则转3.(2 (3) 执行op B(即合并已知量),令得到的新常数为P。如 果NODE(B)是处理当前四元式时新构造出来的结点,则删除它。 如果NODE(P)无定义,则构造一用P做标记的叶结点n。置NODE (P)=n,转4.。 (4) 执行B op C(即合并已知量),令得到的新常数为P。如 果NODE(B)或NODE(C)是处理当前四元式时新构造出来的结 点,则删除它。如果NODE(P)无定义,则构造一用P做标记的叶 结点n。置NODE(P)=n,转4.。
三地址码划分基本块

三地址码划分基本块
三地址码的划分基本块是指将一个程序或函数的三地址码序列
划分为多个基本块的过程,基本块是一个连续的、不包含跳转语句的代码片段。
基本块具有以下特点:
从入口执行到出口,没有跳转到基本块中间的语句。
基本块的入口只能是第一条语句或是上一基本块的出口。
基本块的出口只能是最后一条语句或是下一基本块的入口。
下面是一个简单的示例来说明三地址码划分基本块的过程:
原始的三地址码序列:
1: x = a + b2: if x > c goto 53: y = a - b4: if y < z goto 65: w = a * b6: print(w)
划分后的基本块:基本块1:
1: x = a + b2: if x > c goto 5
基本块2:
3: y = a - b4: if y < z goto 6
基本块3:
复制代码
5: w = a * b6: print(w)
基本块的划分通常通过遍历三地址码序列,根据跳转语句(如条件语句、无条件跳转等)的出现来确定基本块的边界。
划分基本块是许多编译器优化和代码生成算法的基础,它能够帮助对程序进行更好的分析和优化。
中间代码基本块划分

中间代码基本块的划分任务要求在理解代码优化原理的基础上,实现将中间代码序列划分基本块的程序1.理解编译过程中代码优化的定义2.掌握各种代码优化的方法3.定义程序流图中的基本块4.明确程序流图的形式及功能5.程序设计及调试一.原理阐述1.代码优化的定义:代码优化的实质就是提高代码质量从而加快代码执行速度的一种技术。
根据代码优化是否涉及具体的计算机,又将代码优化分为⑴与机器有关的优化(即窥孔优化),一般在目标代码上进行;⑵与机器无关的优化,常在中间代码上进行。
又根据优化范围分成局部优化、循环优化、全局优化。
2.代码优化的方法:1)删除公共子表达式2)代码外提3)强度削弱4)删除归纳变量5)合并已知量6)复写传播7)删除无用赋值3.基本块和划分基本块的定义和方法:定义:基本块就是代码序列中一组顺序执行的语句序列,只有一个入口和一个出口。
而划分基本块的实质就是定义入口和出口语句。
划分基本块的方法:1)定义入口语句①四元式的第一个语句;②由条件转移语句或无条件转移语句能转到的语句;③紧跟在条件转移语句后面的语句。
2)定义出口语句①下一个入口语句的前导语句;②转移语句(包括转移语句本身);③停语句(包括停语句本身)。
构造基本块,删除不属于任何基本块的语句二.流程示意图按四元式序列,给出如下程序流图⑴ read x ; ⑵ read y ; ⑶ L1:c=c+1;⑷ if c=0 goto L2; ⑸ x=y ; ⑹ y=c ;⑺ goto L1; ⑻ L2: write y ; ⑼ halt (以“~ ”表示)三. 部分代码:入口条件1int i=0,j=-1,back_i=0,in_num=0,out_num=0;char g[200];cout<<"请输入要进行基本块划分的四元式(按回车表示四元式输入完毕):"<<endl; for(i=0;i<200;i++){g[i]=' ';c[i]=' ';} //g[](局部),c[](全局),清零gets(g); //输入四元式for(i=0;i<200;i++) {c[i]=g[i];} //将输入的四元式备份到c[]in[in_num++]='1'; //首句为入口语句,将语句序号放入in[](3) L1: c=c+1(4) if c=0 goto L2⑴ read x⑵ read y(5) x=y(6) y=c(7) goto L1⑻ L2: write x ⑼ halt (以“~ ”表Block 3Block 2Block 4 Block 1入口条件2for(i=0;*(g+i)!='~';i++) //由条件转移语句或无条件转移语句能转到的语句为入口语句{if(*(g+i)==':') //找到转移语句能转到的语句{back_i=i; //i是指针,back_i记录当前位置,用于搜索语句序号for (;*(g+back_i)!=')';back_i--){continue;}in[in_num++]=*(g+back_i-1); //得到入口语句序号,将其放入in[]出口条件1out[out_num++]=(char)((int)*(g+back_i-1)-1);break;//入口语句的上一句是出口语句,将其序号放入out[] }}cout<<"_______________________________"<<endl<<endl;cout<<"判定输出语句/输入语句过程(输出语句—>输入语句):"<<endl<<endl;for(;j!=0;j++){cout<<"sentence ("<<out[out_num-1]<<") --> ("<<in[in_num-1]<<")"<<endl;}入口条件3for(i=0;*(g+i)!='~';i++) //紧跟在条件语句后面的语句为入口语句{if(*(g+i)=='i'&&*(g+i+1)=='f') //找到条件语句关键字if{back_i=i;for(;*(g+back_i)!='(';back_i++) //找到条件语句的下一句,即入口语句{continue;}in[in_num++]=*(g+back_i+1); //将入口语句序号放入in[] }}出口条件2for(i=0;*(g+i)!='~';i++) //转移语句为出口语句{if(*(g+i)=='g'&&*(g+i+1)=='o') //找到转移语句的关键字goto{back_i=i;for(;*(g+back_i)!=')';back_i--){continue;}out[out_num++]=*(g+back_i-1); //将语句序号放入out[]in[in_num++]=(char)((int)*(g+back_i-1)+1);//其下一句是入口语句,将语句序号放入in[]for(;j<1;j++){cout<<"sentence ("<<out[out_num-1]<<") --> ("<<in[in_num-1]<<")"<<endl;}for(;*(g+back_i)!='L';back_i++) //找到转移语句能够转到的语句序号{continue;}for(;*(c+ch)!='~';ch++){for(;*(c+ch)!='L';ch++) {continue;}if(*(g+back_i+1)==*(c+ch+1)&&back_i!=ch)//根据语句序号找到相应的语句{back_ch=ch;for(;*(c+back_ch)!=')';back_ch--){continue;}cout<<"sentence ("<<out[out_num-1]<<")--> ("<<*(c+back_ch-1)<<")"<<endl;break; //输出转移}}ch=0;}}出口条件3for(i=0;*(g+i)!='~';i++) //停语句为出口语句,找到停语句{continue;}back_i=i;for(;*(g+back_i)!=')';back_i--){continue;}out[out_num++]=*(g+back_i-1); //将语句序号放入out[] cout<<"_______________________________"<<endl<<endl;cout<<"划分好的代码块:"<<endl;for(i=0;i<4;i++){cout<<"Block[ "<<i+1<<" ]: ("<<in[i]<<") -- ("<<out[i]<<")"<<endl;}//输出各基本块内的语句四.程序运行结果1. 运行输入的四元式:2. 输出结果:划分好的基本代码块五.总结这次我主要负责中间代码基本块的划分。
basic block 基本块

basic block 基本块基本块(basic block)是在程序控制流图中的一段连续的代码,它包含了一组顺序执行的指令。
在编译器优化和静态分析中,基本块是一个重要的概念。
本文将对基本块进行详细介绍,并探讨其在编译器优化和静态分析中的应用。
一、基本块的定义基本块是一段连续的代码,它由一组顺序执行的指令组成。
基本块的起始指令称为入口指令(entry instruction),结束指令称为出口指令(exit instruction)。
基本块中的每一条指令都会被执行一次,且不存在跳转指令(如条件跳转、函数调用等)。
二、基本块的特点1. 基本块是一个不可分割的执行单元,不存在内部的跳转指令。
2. 基本块的入口只有一个,即入口指令。
3. 基本块的出口只有一个,即出口指令。
4. 基本块中的指令顺序是线性的,不会出现分支或循环结构。
三、基本块的构建方法基本块的构建方法有多种,常见的有以下两种:1. 直接法(straight-line code method):根据程序的控制流图,将连续的指令序列构建为一个基本块。
当遇到跳转指令时,会将其后续的指令序列构建为一个新的基本块。
2. 划分法(partition method):通过分析程序的控制流图,将指令序列划分为多个基本块。
划分基本块的依据通常是跳转指令或标签。
四、基本块的应用基本块在编译器优化和静态分析中有着重要的应用,主要包括以下几个方面:1. 代码优化:编译器可以对基本块进行各种优化,例如循环展开、常量传播、死代码消除等。
基本块的线性结构使得这些优化可以更加精确地应用于代码中的特定区域,从而提高程序的执行效率。
2. 控制流分析:静态分析工具可以通过对基本块的分析,获取程序的控制流信息。
例如,可以检测循环结构、判断条件的复杂度、函数调用的层次等,从而帮助开发人员理解和调试程序。
3. 污点分析:基于基本块的污点分析可以跟踪程序中的敏感数据,如用户输入或密码。
中间代码基本块划分

中间代码基本块的划分任务要求在理解代码优化原理的基础上,实现将中间代码序列划分基本块的程序1.理解编译过程中代码优化的定义2.掌握各种代码优化的方法3.定义程序流图中的基本块4.明确程序流图的形式及功能5.程序设计及调试一.原理阐述1.代码优化的定义:代码优化的实质就是提高代码质量从而加快代码执行速度的一种技术。
根据代码优化是否涉及具体的计算机,又将代码优化分为⑴与机器有关的优化(即窥孔优化),一般在目标代码上进行;⑵与机器无关的优化,常在中间代码上进行。
又根据优化范围分成局部优化、循环优化、全局优化。
2.代码优化的方法:1)删除公共子表达式2)代码外提3)强度削弱4)删除归纳变量5)合并已知量6)复写传播7)删除无用赋值3.基本块和划分基本块的定义和方法:定义:基本块就是代码序列中一组顺序执行的语句序列,只有一个入口和一个出口。
而划分基本块的实质就是定义入口和出口语句。
划分基本块的方法:1)定义入口语句①四元式的第一个语句;②由条件转移语句或无条件转移语句能转到的语句;③紧跟在条件转移语句后面的语句。
2)定义出口语句①下一个入口语句的前导语句;②转移语句(包括转移语句本身);③停语句(包括停语句本身)。
构造基本块,删除不属于任何基本块的语句二.流程示意图按四元式序列,给出如下程序流图⑴read x;⑵read y;⑶L1:c=c+1;⑷if c=0 goto L2;⑸x=y;⑹y=c;⑺goto L1;⑻L2: write y;⑼halt(以“~ ”表示)三.部分代码:入口条件1int i=0,j=-1,back_i=0,in_num=0,out_num=0;char g[200];cout<<"请输入要进行基本块划分的四元式(按回车表示四元式输入完毕):"<<endl; for(i=0;i<200;i++){g[i]=' ';c[i]=' ';} //g[](局部),c[](全局),清零gets(g); //输入四元式for(i=0;i<200;i++) {c[i]=g[i];} //将输入的四元式备份到c[]in[in_num++]='1'; //首句为入口语句,将语句序号放入in[]for(i=0;*(g+i)!='~';i++) //由条件转移语句或无条件转移语句能转到的语句为入口语句{if(*(g+i)==':') //找到转移语句能转到的语句{back_i=i; //i是指针,back_i记录当前位置,用于搜索语句序号for (;*(g+back_i)!=')';back_i--){continue;}in[in_num++]=*(g+back_i-1); //得到入口语句序号,将其放入in[]出口条件1out[out_num++]=(char)((int)*(g+back_i-1)-1);break;//入口语句的上一句是出口语句,将其序号放入out[] }}cout<<"_______________________________"<<endl<<endl;cout<<"判定输出语句/输入语句过程(输出语句—>输入语句):"<<endl<<endl;for(;j!=0;j++){cout<<"sentence ("<<out[out_num-1]<<") --> ("<<in[in_num-1]<<")"<<endl;}for(i=0;*(g+i)!='~';i++) //紧跟在条件语句后面的语句为入口语句{if(*(g+i)=='i'&&*(g+i+1)=='f') //找到条件语句关键字if{back_i=i;for(;*(g+back_i)!='(';back_i++) //找到条件语句的下一句,即入口语句{continue;}in[in_num++]=*(g+back_i+1); //将入口语句序号放入in[] }}出口条件2for(i=0;*(g+i)!='~';i++) //转移语句为出口语句{if(*(g+i)=='g'&&*(g+i+1)=='o') //找到转移语句的关键字goto{back_i=i;for(;*(g+back_i)!=')';back_i--){continue;}out[out_num++]=*(g+back_i-1); //将语句序号放入out[]in[in_num++]=(char)((int)*(g+back_i-1)+1);//其下一句是入口语句,将语句序号放入in[]for(;j<1;j++){cout<<"sentence ("<<out[out_num-1]<<") --> ("<<in[in_num-1]<<")"<<endl;}for(;*(g+back_i)!='L';back_i++) //找到转移语句能够转到的语句序号{continue;}for(;*(c+ch)!='~';ch++){for(;*(c+ch)!='L';ch++) {continue;}if(*(g+back_i+1)==*(c+ch+1)&&back_i!=ch)//根据语句序号找到相应的语句{back_ch=ch;for(;*(c+back_ch)!=')';back_ch--){continue;}cout<<"sentence ("<<out[out_num-1]<<")--> ("<<*(c+back_ch-1)<<")"<<endl;break; //输出转移}}ch=0;}}出口条件3for(i=0;*(g+i)!='~';i++) //停语句为出口语句,找到停语句{continue;}back_i=i;for(;*(g+back_i)!=')';back_i--){continue;}out[out_num++]=*(g+back_i-1); //将语句序号放入out[] cout<<"_______________________________"<<endl<<endl;cout<<"划分好的代码块:"<<endl;for(i=0;i<4;i++){cout<<"Block[ "<<i+1<<" ]: ("<<in[i]<<") -- ("<<out[i]<<")"<<endl;}//输出各基本块内的语句四.程序运行结果1. 运行输入的四元式:2. 输出结果:划分好的基本代码块五.总结这次我主要负责中间代码基本块的划分。
24第二十四讲

(16) …...
B4
代码外提后 B1 (1)i:=1 B2’ (3)t1:=2*j (7)t5:=2*j (6)t4:=a0-11 (10)t8:=a0-11
(2)if i>10 goto (16)
(4)t2:=10*i (8)t6:=10*i (11)t9:=t8[t7] (13)t4[t3]:=t10 (15)goto (2) (5)t3:=t2+t1 (9)t7:=t6+t5 (12)t10:=t9+1 (14)i:=i+1
删除多余运算,代码外提
(1)PROD := 0 (2)I := 1 (4)T2 := a0 – 4 (7) T5 := b0 – 4 (3) T1 := 4 * I (5)T3 := T2[T1] (6)T4 := T1 (8) T6 := T5[T4] (9) T7 := T3 * T6 (10) PROD := PROD + T7 (11) I := I +1 (12)if I≤20 goto (3)
优化后
S1 : = R + r A : = 6.28 * S1 S2 : = R - r B : = A * S2
五. 循环优化
1. 循环的定义 循环是程序流图中有唯一入口结点 的强连通子图。
(1)入口结点 子图中满足下列条件的结点n: 或者n是流图的首结点, 或者在子图外有一 结点m, 它有一有向边mn引向结点n; (2)强连通子图。
例:
1 2
{5,6,7,8,9}是一循环 {4,5},{2,4}均不是循环
3
4 5 6 7 8
9
10 图6-3
2. 循环的查找
(1)必经结点: 从流图的首结点出发到达结点 n的任一通路都必须经过的结点d, 称为n的 必经结点,记为d DOM n 根据定义可知: 每个结点是它本身的必经结点,即n DOM n 流图的首结点是流图中任一结点的必经结点, 即n0 DOM n
杭电编译原理名词解释

名词解析1.编译器: 一个编译程序就是一个语言翻译程序,它把一种语言(称作源语言)书写的程序翻译成另一种语言(称作目标语言)书写的等价的程序。
2.词法分析:从左至右读源程序,识别单词符号3.语法分析:在词法分析的基础上将单词序列组合成各类语法短语4.语义分析:语义检查,收集语义信息,进行类型审查5.代码优化:对中间代码进行优化(提高时间与空间效率6.遍:对源程序或源程序中间表示的一次扫描,每一遍读入一个文件,执行一个或几个阶段的编译操作,并输出源程序的一个中间表示7.上下文无关文法:所定义的的语法单位是完全独立于这种语法单位可能出现的上下文环境的8.推导与归约:推导是用产生式的右部代替左部,归约是用产生式的左部代替右部,归约是推导的逆过程9.最左/右推导:对句型最左/右非终结符进行展开10.最左/右规约:最右/左推导的逆过程,即对最左/右边的可归约串进行归约11.句型:从文法的开始符号出发进行零步或多于零步的推导得到的文法符号串12.句子:只包含终结符号的句型称为句子13.句柄:最左直接短语14.句子、文法、语言的二义性:如果一个文法的句子有两棵或两棵以上的分析树,称此句子是二义的如果一个文法有一个句子是二义的,此文法称为二义文法如果一个语言的所有文法都是二义的,称此语言是二义的15.正规表达式:一个表示字符串格式的模式,可以用来描述单词符号的结构16.有限自动机:是具有离散输入与离散输出的一种数学模型,输入字符串,输出是、否17.不确定的有限自动机:由状态集合,输入符号集合,转换函数,开始状态,接受状态集合组成18.确定的有限自动机:没有ε边转移且一个状态面临一个输入符号时最多只转移到一个状态的NFA19.自顶向下分析:从根到叶子来建立句子的分析树或,给出句子的一个从开始符号出发的推导序列20.自底向上分析:从叶子到根来建立句子的分析树或,给出一个从句子出发到开始符号的归约序列21.综合属性:属性值是分析树中该结点的子结点的属性值的函数22.继承属性:属性值是分析树中该结点的父结点和/或兄弟结点的属性值的函数23.S -属性定义:只含有综合属性的语法制导定义24.L -属性定义:是一种语法制导定义L-属性定义包含S-属性定义25.代码优化:对中间代码进行优化(提高时间与空间效率)26.基本块:·一个连续的三地址(中间)代码序列·只有一个入口语句,一个出口语句·执行时从入口语句进入,从出口语句退出27.活动记录:是一段连续的存储区,用以存放过程的一次执行所需要的信息,如局部数据。
编译原理_国防科技大学中国大学mooc课后章节答案期末考试题库2023年

编译原理_国防科技大学中国大学mooc课后章节答案期末考试题库2023年1.对于文法G(S'),该文法识别活前缀的DFA如下图,状态I5包含的项目有G(S'):(0) S' → S(1) S → iSeS(2) S → iS(3) S → a【图片】答案:S → iSeŸS_S → ŸiSeS_S → ŸiS_S → Ÿa2.(a+b)/(c-d)对应的逆波兰式(后缀式)是答案:ab+cd-/3.表达式(a+b)/c-(a+b)*d对应的间接三元式表示如下,其中三元式表中第(3)号三元式应为间接码表三元式表(1) OP ARG1 ARG2 (2) (1) + a b (1) (2) / (1)c (3) (3) (4) (4) - (2) (3)答案:( *, (1), d)4.设AS 为文法的综合属性集, AI 为继承属性集, 则对于下面的属性文法G(P)定义中,AS和AI正确描述是产生式语义规则P → xQR Q.b:=R.d R.c:=1R.e:=Q.a Q → u Q.a:=3 R → v R.d:=R.c R.f:=R.e答案:AS={ Q.a, R.d, R.f } AI={ Q.b, R.c, R.e }5.考虑下面的属性文法G(S)【图片】过程enter(name, type)用来把名字name填入到符号表中,并给出此名字的类型type。
按照该属性文法,关于语句【图片】 , 【图片】 , 【图片】:integr的语义描述准确的是答案:说明 , , 是integer变量,把 , , 三个名字填入符号表中,并在类型栏中填上integer6.考虑下面的属性文法G(S)【图片】对于输入字符串abc进行自下而上的语法分析和属性计算,设S.u的初始值为5,属性计算完成后,S.v的值为答案:187.关于属性文法,下列说法中正确的是答案:属性文法是对上下文无关文法的扩展。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
中间代码基本块的划分
任务要求
在理解代码优化原理的基础上,实现将中间代码序列划分基本块的程序
1.理解编译过程中代码优化的定义
2.掌握各种代码优化的方法
3.定义程序流图中的基本块
4.明确程序流图的形式及功能
5.程序设计及调试
一.原理阐述
1.代码优化的定义:
代码优化的实质就是提高代码质量从而加快代码执行速度的一种技术。
根据代码优化是否涉及具体的计算机,又将代码优化分为⑴与机器有关的优化(即窥孔优化),一般在目标代码上进行;⑵与机器无关的优化,常在中间代码上进行。
又根据优化范围分成局部优化、循环优化、全局优化。
2.代码优化的方法:
1)删除公共子表达式
2)代码外提
3)强度削弱
4)删除归纳变量5)合并已知量
6)复写传播
7)删除无用赋值
3.基本块和划分基本块的定义和方法:
定义:基本块就是代码序列中一组顺序执行的语句序列,只有一个入口和一个出口。
而划分基本块的实质就是定义入口和出口语句。
划分基本块的方法:
1)定义入口语句
①四元式的第一个语句;
②由条件转移语句或无条件转移语句能转到的语句;
③紧跟在条件转移语句后面的语句。
2)定义出口语句
①下一个入口语句的前导语句;
②转移语句(包括转移语句本身);
③停语句(包括停语句本身)。
构造基本块,删除不属于任何基本块的语句
二.流程示意图
按四元式序列,给出如下程序流图
⑴ read x ; ⑵ read y ; ⑶ L1:c=c+1;
⑷ if c=0 goto L2; ⑸ x=y ; ⑹ y=c ;
⑺ goto L1; ⑻ L2: write y ; ⑼ halt (以“~ ”表示)
三. 部分代码:
入口条件1
int i=0,j=-1,back_i=0,in_num=0,out_num=0;
char g[200];
cout<<"请输入要进行基本块划分的四元式(按回车表示四元式输入完毕):"<<endl; for(i=0;i<200;i++)
{g[i]=' ';c[i]=' ';} //g[](局部),c[](全局),清零
gets(g); //输入四元式
for(i=0;i<200;i++) {c[i]=g[i];} //将输入的四元式备份到c[]
in[in_num++]='1'; //首句为入口语句,将语句序号放入in[]
(3) L1: c=c+1
(4) if c=0 goto L2
⑴ read x
⑵ read y
(5) x=y
(6) y=c
(7) goto L1
⑻ L2: write x ⑼ halt (以“~ ”表Block 3
Block 2
Block 4 Block 1
入口条件2
for(i=0;*(g+i)!='~';i++) //由条件转移语句或无条件转移语句能转到的语句为入口语句{
if(*(g+i)==':') //找到转移语句能转到的语句
{
back_i=i; //i是指针,back_i记录当前位置,用于搜索语句序号
for (;*(g+back_i)!=')';back_i--)
{continue;}
in[in_num++]=*(g+back_i-1); //得到入口语句序号,将其放入in[]
出口条件1
out[out_num++]=(char)((int)*(g+back_i-1)-1);break;
//入口语句的上一句是出口语句,将其序号放入out[] }
}
cout<<"_______________________________"<<endl<<endl;
cout<<"判定输出语句/输入语句过程(输出语句—>输入语句):"<<endl<<endl;
for(;j!=0;j++)
{cout<<"sentence ("<<out[out_num-1]<<") --> ("<<in[in_num-1]<<")"<<endl;}
入口条件3
for(i=0;*(g+i)!='~';i++) //紧跟在条件语句后面的语句为入口语句{
if(*(g+i)=='i'&&*(g+i+1)=='f') //找到条件语句关键字if
{
back_i=i;
for(;*(g+back_i)!='(';back_i++) //找到条件语句的下一句,即入口语句
{continue;}
in[in_num++]=*(g+back_i+1); //将入口语句序号放入in[] }
}
出口条件2
for(i=0;*(g+i)!='~';i++) //转移语句为出口语句
{
if(*(g+i)=='g'&&*(g+i+1)=='o') //找到转移语句的关键字goto
{
back_i=i;
for(;*(g+back_i)!=')';back_i--)
{continue;}
out[out_num++]=*(g+back_i-1); //将语句序号放入out[]
in[in_num++]=(char)((int)*(g+back_i-1)+1);
//其下一句是入口语句,将语句序号放入in[]
for(;j<1;j++)
{cout<<"sentence ("<<out[out_num-1]<<") --> ("<<in[in_num-1]<<")"<<endl;}
for(;*(g+back_i)!='L';back_i++) //找到转移语句能够转到的语句序号
{continue;}
for(;*(c+ch)!='~';ch++)
{
for(;*(c+ch)!='L';ch++) {continue;}
if(*(g+back_i+1)==*(c+ch+1)&&back_i!=ch)
//根据语句序号找到相应的语句
{
back_ch=ch;
for(;*(c+back_ch)!=')';back_ch--)
{continue;}
cout<<"sentence ("<<out[out_num-1]<<")--> ("<<*(c+back_ch-1)<<")"<<endl;
break; //输出转移
}
}
ch=0;
}
}
出口条件3
for(i=0;*(g+i)!='~';i++) //停语句为出口语句,找到停语句
{continue;}
back_i=i;
for(;*(g+back_i)!=')';back_i--)
{continue;}
out[out_num++]=*(g+back_i-1); //将语句序号放入out[] cout<<"_______________________________"<<endl<<endl;
cout<<"划分好的代码块:"<<endl;
for(i=0;i<4;i++)
{cout<<"Block[ "<<i+1<<" ]: ("<<in[i]<<") -- ("<<out[i]<<")"<<endl;}
//输出各基本块内的语句四.程序运行结果
1. 运行输入的四元式:
2. 输出结果:划分好的基本代码块
五.总结
这次我主要负责中间代码基本块的划分。
有了上次词法分析器的程序设计的经验,我以书中的实例为参考模型,进行编程,这样就避免了由空想带来的不必要的麻烦。
整个设计还是以c++中的模块化设计为主。
特别是在语句类型判断上,在编写代码时,虽然只要遵守判断规则,但仍然遇上了不困难,为了能方便的分块,使程序能更加简便、易懂,我还自行将语句按规则分为三类。
同时在这次设计过程中,也加强了我们的团队合作力,大家互相帮助,在交流过程中,也学习到不少他人在思考过程中的长处,弥补了自己不少欠考虑的地方,受益良多。
最后非常感谢卜老师给予的指导。