编译原理中间代码优化Word版

合集下载

编译原理,中间代码优化与目标代码生成

编译原理,中间代码优化与目标代码生成

删除公共 子表达式
t11=t2 x=a[t11] t12=t11 t13=t1 t14=a[t13] a[12]=t14 t14=t13 a[15]=x
在B1中t1=4*n;
目标代码生成
• 目标代码生成是编译最后一个阶段,它把 中间代码转换成汇编指令或可重定位的目 标代码。
• 对于语句 • x = y + z – m * 10; • 可以产生IBM PC汇编 指令
B6 t11=4*I x=a[t11] t12=4*I t13=4*n t14=a[t13] a[12]=t14 t14=4*n a[15]=x
t6=4*i x=a[t6] t7=4*i t8=4*j t9=a[t8] a[t7]=t9 t10=4*j a[t10]=x goto b2
B5
删除公共 子表达式
对中间代码进行变换加工以便在最后产生高效的目标代码
中间代码优化
• 对中间代码进行变换加工,以便在最后产 生高效的目标代码。
例:快速排序程序
Void quicksort(a,m,n); Int m,n,a[]; { int I,j; int v,x; if(n<=m) return; I=m-1;j=n;v=a[n] While(1){ Do {I=I+1;}while (a[I]<v); Do{j=j-1;}while(a[j]>v); If(I>=j)break; X=a[I];a[I]=a[j];a[j]=x; } X=a[I];a[I]=a[n];a[n]=x; Quicksort(m,j);quicksort(I+1,n); }
i=i+1 t2=4*i t3=a[t2] If t3<v goto B2 j=j-1 t4=4*j t5=a[t4] If t5<v goto B3 If I>=j goto b6

编译器设计中的语法分析和中间代码优化

编译器设计中的语法分析和中间代码优化

编译器设计中的语法分析和中间代码优化在编译器的设计中,语法分析和中间代码优化是两个重要的阶段。

语法分析是将输入的源代码转化为语法树的过程,而中间代码优化则是对生成的中间代码进行改进,以提高目标代码的执行效率和代码质量。

一、语法分析语法分析是编译器设计中的一个重要环节,它的主要任务是将输入的源代码转化为一棵语法树。

语法树是编译器在进一步处理代码之前生成的一种数据结构,它以树的形式表示代码的语法结构。

在语法分析阶段,编译器会对源代码进行词法分析,并根据语法规则构建语法树。

1. 词法分析词法分析是将源代码分解为一个个的词法单元(Token)的过程。

每个Token代表着源代码中的一个有意义的单词,如变量名、操作符、关键词等等。

编译器会通过词法分析器识别出这些词法单元,并将其传递给语法分析器进行后续处理。

2. 语法规则语法规则定义了源代码中各种语句和表达式的结构和组织方式。

在语法分析阶段,编译器会根据这些语法规则来构建语法树。

语法规则一般使用上下文无关文法(Context-Free Grammar)来描述。

3. 构建语法树通过词法分析和语法规则,编译器可以逐步构建语法树。

语法树是一种树状数据结构,以根节点表示整个代码块,每个内部节点表示一个语法单元,叶节点表示一个词法单元。

编译器可以根据语法树进行后续的语义分析和代码生成。

二、中间代码优化中间代码优化是编译器设计的另一重要环节,它的主要目标是改进生成的中间代码,以提高目标代码的执行效率和代码质量。

在中间代码优化阶段,编译器会对生成的中间代码进行分析和改进。

1. 常量传播常量传播是一种中间代码优化技术,它的目标是将程序中的常量表达式计算出实际的结果,并将结果用于后续的代码生成。

常量传播可以减少运行时的计算量,提高程序的执行效率。

2. 冗余代码消除冗余代码是指程序中不会被执行的代码,它们不会对程序的结果产生任何影响。

冗余代码消除可以通过分析中间代码的控制流来判断哪些代码是冗余的,并将其消除掉。

编译原理-陈火旺版-第一章

编译原理-陈火旺版-第一章

编译器的作用与重要性
01
编译器是将高级语言程序翻译成机器语言程序的软件工具,是 软件开发的基础设施之一。
02
编译器可以提高程序的执行效率,使得程序能够在各种计算机
上运行。
编译器还可以对程序进行优化,提程简介
01
02
03
词法分析
将输入的源程序分解成一 个个的单词符号,即词法 单元。
词法分析器的构造
构造原理
根据词法规则构造出识别相应单 词符号的有限自动机,然后将有 限自动机转换为对应的程序代码
构造方法
手工构造法、自动生成法
注意事项
处理好单词符号的二义性问题; 识别出源程序中的错误并进行适 当的处理。
04
语法分析
语法分析概述
语法分析的任务
根据语言的语法规则,对输 入的符号序列进行合法性检 查,并构造出相应的语法结
中间代码的形式
常见的中间代码形式有三地址码、四元式、树形表示等。
中间代码生成算法
根据源程序的语法结构和语义规则,生成相应的中间代码序列。
符号表管理
符号表的作用
符号表用于记录源程序中各种标识符的属性信息,如类型、作用域 和存储地址等。
符号表的组织方式
常见的符号表组织方式有线性表、散列表和树形结构等。
循环优化
通过循环展开、循环合并、循环交换等技术来改进循环的性能。
目标代码生成方法
机器无关代码生成
机器相关代码生成
生成与特定机器无关的中间代码,然后在 运行时将其转换为特定机器上的目标代码 。
直接生成特定机器上的目标代码,这需要 考虑机器的指令集、寄存器分配、内存访 问等因素。
汇编语言代码生成
高级语言虚拟机代码生成

编译原理 中间代码优化

编译原理 中间代码优化

实验三中间的代码优化某些编译程序在中间代码或目标代码生产之后要对其进行优化,所谓优化就是对代码进行等价的变换。

而变换后的代码运行结果与变换前的代码运行结果相同。

而运行速度加快或占用内存空间减少。

中间的代码优化就是对中间代码进行等价的变换。

基本块的有向图DAG(Directed Acyclic Graph)有向图中任何一条通路都不是环路,则称该有向图为无环路有向图,简称为DAG。

一、实验题目:中间代码的局部优化二、实验目的:掌握局部优化方法、提高机器的运行速度三、实验内容:1 、构造基本块内的优化DAG假设:(1)ni 为已知结点号,n为新结点号;(2)访问各结点信息时,按结点号逆序排序2、完成对下例三类表达式的优化(1)常值表达式的优化(2)公共表达式的优化(3)无用赋值的优化3、输出根据优化的DAG重组四元式四、设计概要:首先要实现表达式中间代码生成,采用递归下降子程序法实现。

E→T{ω0 “push(SYN,w)”T“QUAT” }T→F{ω1”push(SYN,w)”F“QUAT”}F→i“push(SEM,entry(w))”|(E)其中:·push(SYN,w)---当前单词w入符号栈SYN;·push(SEM,entry(w))--- 当前i在符号表中的入口值压入语义栈SEM;·QUAT---生成四元式函数①T:=newtemp;②QT[j]=(SYN[k],SEM[s-1],SEM[s],T);j++;③ pop(SYN,_);pop(SEM,_);pop(SEM,_); push(SEM,T);在对中间代码进行局部优化五、程序代码及运行结果:1.表达式中间代码生成#include<iostream>#include<cstdlib>using namespace std;char str[50];char sem[50];char syn[50];char ch;int i=0;int j=0;int n=0;int p=1;void push_sem(char w){sem[j++]=w;}void push_syn(char w){syn[n++]=w;}void Gen(){char s[2][2];char w;w=sem[--j];if(w>='1'&&w<='9'){s[0][1]=w;s[0][0]=sem[--j];}else{s[0][0]=w;s[0][1]=' ';}w=sem[--j];if(w>='1'&&w<='9'){s[1][1]=w;s[1][0]=sem[--j];}else{s[1][0]=w;s[1][1]=' ';}cout<<"("<<syn[--n]<<","<<s[1][0]<<s[1][1]<<","<<s[0][0]<<s[0][1] <<","<<'t'<<p++<<")"<<endl;push_sem('t');push_sem(p+47);}int F(){int m;int E();if(ch=='('){ch=str[i++];m=E();if(ch==')') ch=str[i++];else{//cout<<"表达式error!"<<endl;return 0;}}else{if((ch>='a'&&ch<='z')||(ch>='1'&&ch<='9')){push_sem(ch);ch=str[i++];}else{//cout<<"表达式error!"<<endl;return 0;}}return 1;}int T(){int k,m,l;k=F();if(k==0){return 0;}while(1){//push_syn(ch);if(ch=='*'){push_syn(ch);ch=str[i++];m=F();if(m==0){return 0;}Gen();}else if(ch=='/'){push_syn(ch);ch=str[i++];l=F();if(l==0){return 0;}Gen();}else break;}return 1;}int E(){int k,m,l;k=T();if(k==0){return 0;}while(1){//push_syn(ch);if(ch=='+'){push_syn(ch);ch=str[i++];m=T();if(m==0){return 0;}Gen();}else if(ch=='-'){push_syn(ch);ch=str[i++];l=T();if(l==0){return 0;}Gen();}else break;}return 1;}int main(){int k,q=0;char w1,w2,w;char s[1][2];cout<<"输入表达式(以'#'结束):";cin>>str;w1=str[i++];w2=str[i++];if(w2!='=') {i=i-2;q=1;}ch=str[i++];k=E();if(q==0){w=sem[--j];if(w>='1'&&w<='9'){s[0][1]=w;s[0][0]=sem[--j];}else{s[0][0]=w;s[0][1]=' ';}cout<<"("<<w2<<","<<s[0][0]<<s[0][1]<<","<<" "<<","<<w1<<")"<<endl;}if(k==0) cout<<"error!"<<endl;else{if(ch=='#') cout<<"OK!"<<endl;else cout<<"error!"<<endl;}return 0;}运行结果:2.代码优化:(采用递归下降子程序法判断表达式是否合法,方法如上)#include <iostream>#include <cstdlib>#include <string.h>using namespace std;int i=1;int j=0,n=0;int p;int m=1;int Ti=0;char prog[100];char ch;char syn[20],sem[50][3];void SEM(void){int i,j;for(i=0;i<50;i++)for(j=0;j<3;j++)sem[i][j]='\0';}struct quat//四元式结构{char result[8];char ag1[8];char op;char ag2[8];}quad[25],newquad[15];struct Ni//节点结构{int pre[2];char op;char bz[25][8];}N[25];void newN(void){int l,j;i++;for(j=0;j<25;j++){for(l=0;l<8;l++){N[i-1].bz[j][l]='\0';}}for(j=0;j<2;j++)N[i-1].pre[j]=0;N[i-1].op='\0';}void dagt(void);void newquat(void);void fuzhi(void);//递归语法分析生成中间代码void E(void);void T(void);void F(void);void pop0(char sz[]);void push0(char sz[],char x);void pop1(char sz[50][3]);void push1(char sz[50][3],char x[3]); void quat1(void);void quat0(char w);void print1(void);void print2(void);char *newT(void){char *p;char m[8];p=(char *)malloc(8);Ti++;itoa(Ti,m,10);strcpy(p+1,m);p[0]='t';return(p);}void main(){p=0;syn[0]='#';SEM();sem[0][0]='#';cout<<"请输入表达式:"<<endl;do{cin.get(ch);if(ch != '\n') prog[p++]=ch;}while(ch!='#');p=0;ch=prog[p++];while(ch!='#'){fuzhi();}print1();dagt();newquat();print2();}void fuzhi(void){char temp[3];temp[0]='\0';temp[1]='\0';temp[2]='\0';if((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')) {temp[0]=ch;push1(sem,temp);ch=prog[p++];if(ch=='='){push0(syn,ch);ch=prog[p++];E();if(m==0){cout<<"错误1!"<<endl;system("pause"); /////return;}if(ch==';'){ch=prog[p++];quat1();}else{cout<<"错误2!"<<endl;system("pause");return;}}else{cout<<"错误3!"<<endl;system("pause");return;}}else{cout<<"错误4!"<<endl;printf("%d",ch);system("pause");return;}}//E、T、F是递归下降子程序的语法分析void E(void){char w;T();while(ch=='+'||ch=='-'){push0(syn,ch);w=syn[strlen(syn)-1];ch=prog[p++];T();quat0(w);}}void T(void){char w;F();while(ch=='*'||ch=='/'){push0(syn,ch);w=syn[strlen(syn)-1];ch=prog[p++];F();quat0(w);}}void F(void){char temp[3];temp[0]='\0';temp[1]='\0';temp[2]='\0';if(ch=='('){ch=prog[p++];E();if(ch==')'){ch=prog[p++];}else m=0;}else if((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')||(ch<='9'&&ch>='0')) {temp[0]=ch;push1(sem,temp);ch=prog[p++];}else m=0;}void push0(char sz[],char x){int top;top=strlen(sz);sz[top]=x;top++;sz[top+1]='\0';}void pop0(char sz[]){int top;top=strlen(sz)-1;sz[top]='\0';}void push1(char sz[50][3],char x[3]) {int top=1;while(sz[top][0])top++;strcpy(sz[top],x);top++;sz[top+1][0]='\0';}void pop1(char sz[50][3]){int top=1;while(sz[top][0])top++;top--;sz[top][0]='\0';sz[top][1]='\0';sz[top][2]='\0';}void quat0(char w){int top=1,i;char *p;while(sem[top][0])top++;strcpy(quad[j].ag1,sem[top-2]);strcpy(quad[j].ag2,sem[top-1]);quad[j].op=w;p=newT();for(i=0;i<8;i++)quad[j].result[i]=p[i];pop1(sem);top--;pop1(sem);top--;for(i=0;i<3;i++)sem[top][i]=quad[j].result[i];sem[top][2]='\0';j++;}void quat1(void){char ag2[8];int top,i;top=1;while(sem[top][0])top++;ag2[0]='_';for(i=1;i<8;i++)ag2[i]='\0';strcpy(quad[j].ag1,sem[top-1]);strcpy(quad[j].ag2,ag2);quad[j].op='=';strcpy(quad[j].result,sem[top-2]);pop0(syn);pop1(sem);pop1(sem);j++;}void print1(void){int i;cout<<"原来的四元组:"<<endl;for(i=0;i<j;i++)cout<<(i+1)<<"、("<<quad[i].op<<","<<quad[i].ag1<<","<<quad[i].ag2<<","<<quad[i].result<<")"<<endl;}void dagt(void){int m,n,top,l,tag=0,tag1=0,tag2=0;char temp;for(m=0;m<j;m++){tag=0;for(n=i;n>0;n--)for(l=0;l<25;l++){if(strcmp(quad[m].ag1,N[n-1].bz[l])==0){tag=n;break;}}if(tag!=0){tag1=tag-1;if('0'<quad[m].ag1[0]&&quad[m].ag1[0]<'9')goto N3;else goto N3;}else{if('0'<quad[m].ag1[0]&&quad[m].ag1[0]<'9'){if(quad[m].ag2[0]!='_'){if('0'<quad[m].ag2[0]&&quad[m].ag2[0]<'9'){quad[m].ag1[0]=quad[m].ag1[0]-'0';quad[m].ag2[0]=quad[m].ag2[0]-'0';switch(quad[m].op){case '+':temp=quad[m].ag1[0]+quad[m].ag2[0];break;case '-':temp=quad[m].ag1[0]-quad[m].ag2[0];break;case '*':temp=quad[m].ag1[0]*quad[m].ag2[0];break;case '/':temp=quad[m].ag1[0]/quad[m].ag2[0];break;default:break;}tag=0;for(n=i;n>0;n--)for(l=0;l<25;l++){if(strcmp(quad[m].result,N[n-1].bz[l])==0){tag=n;break;}}if(tag!=0)continue;else{newN();N[i-1].bz[0][0]=temp+'0' ;strcpy(N[i-1].bz[1],quad[m].result);continue;}}else{newN();tag1=i-1;strcpy(N[i-1].bz[0],quad[m].ag1);goto N2;}}else goto N1;}elseN1:{newN();strcpy(N[i-1].bz[0],quad[m].ag1);tag1=i-1;N3:if(quad[m].ag2[0]=='_'){tag=0;for(n=i;n>0;n--)for(l=0;l<25;l++){if(strcmp(quad[m].result,N[n-1].bz[l])==0){tag=n;top=l;break;}}if(tag!=0){for(l=top+1;l<25;l++){strcpy(N[tag-1].bz[l-1],N[tag-1].bz[l]);}goto N5;}else{N5:if(N[i-1].bz[0][1]){if(quad[m].result[1]){top=0;while(N[tag1].bz[top][0])top++;strcpy(N[tag1].bz[top],quad[m].result);continue;}else{temp=N[i-1].bz[0][1];strcpy(N[i-1].bz[0],quad[m].result);top=0;while(N[tag1].bz[top][0])top++;N[i-1].bz[top][0]='t';N[i-1].bz[top][1]=temp;continue;}}else{top=0;while(N[tag1].bz[top][0])top++;strcpy(N[tag1].bz[top],quad[m].result);continue;}}}elseN2:{tag=0;for(n=i;n>0;n--)for(l=0;l<25;l++){if(strcmp(quad[m].ag2,N[n-1].bz[l])==0){tag=n;break;}}if(tag!=0){tag2=tag-1;tag=0;for(n=i;n>0;n--)if((N[n-1].pre[0]==tag1)&&(N[n-1].pre[1]==tag2)){tag=n;break;}if(tag!=0){if(N[tag-1].op==quad[m].op){if(!N[tag-1].bz[0][1]){top=1;while(N[tag-1].bz[top][0])top++;strcpy(N[tag-1].bz[top],quad[m].result);}else if(!quad[m].result[1]){temp=N[tag-1].bz[0][1];strcpy(N[tag-1].bz[0],quad[m].result);top=1;while(N[tag-1].bz[top][0])top++;N[tag].bz[top][0]='t';N[tag].bz[top][1]=temp;}else{top=1;while(N[tag-1].bz[top][0])top++;strcpy(N[tag-1].bz[top],quad[m].result);}continue;}else{newN();N[i-1].op=quad[m].op;strcpy(N[i-1].bz[0],quad[m].result);N[i-1].pre[0]=tag1;N[i-1].pre[1]=tag2;}continue;}else{newN();N[i-1].op=quad[m].op;strcpy(N[i-1].bz[0],quad[m].result);N[i-1].pre[0]=tag1;N[i-1].pre[1]=tag2;continue;}}else{newN();strcpy(N[i-1].bz[0],quad[m].ag2);tag2=i-1;tag=0;for(n=i;n>0;n--)for(l=0;l<25;l++)if(strcmp(quad[m].result,N[n-1].bz[l])==0){tag=n;top=l;break;}if(tag==0){newN();strcpy(N[i-1].bz[0],quad[m].result);N[i-1].op=quad[m].op;N[i-1].pre[0]=tag1;N[i-1].pre[1]=tag2;continue;}else{for(l=top+1;l<25;l++){strcpy(N[tag-1].bz[l-1],N[tag-1].bz[l]);}newN();strcpy(N[i-1].bz[0],quad[m].result);N[i-1].op=quad[m].op;N[i-1].pre[0]=tag1;N[i-1].pre[1]=tag2;}}}}}}}void newquat(void){int l,top;for(l=1;l<i;l++){if(N[l].pre[1]==0&&N[l].pre[0]==0){if(!N[l].bz[0][1]){if(('0'<N[l].bz[0][0])&&(N[l].bz[0][0]<'9'))continue;else{for(top=1;N[l].bz[top][1];top++){if(!N[l].bz[top][0]){strcpy(newquad[n].ag1,N[l].bz[0]);newquad[n].ag2[0]='_';newquad[n].op='=';strcpy(newquad[n].result,N[l].bz[top]);n++;}}}}else continue;}else if(N[l].pre[1]!=0||N[l].pre[0]!=0){strcpy(newquad[n].ag1,N[N[l].pre[0]].bz[0]);strcpy(newquad[n].ag2,N[N[l].pre[1]].bz[0]);newquad[n].op=N[l].op;strcpy(newquad[n].result,N[l].bz[0]);n++;if(!N[l].bz[0][1]){for(top=1;N[l].bz[top][0];top++){if(!N[l].bz[top][1]){strcpy(newquad[n].ag1,N[l].bz[0]);newquad[n].ag2[0]='_';newquad[n].op='=';strcpy(newquad[n].result,N[l].bz[top]);n++;}}}}}}void print2(void){int i;cout<<"优化后的代码:"<<endl;for(i=0;i<n;i++)cout<<(i+1)<<"、("<<newquad[i].op<<","<<newquad[i].ag1<<","<<newquad[i].ag2<<","<<newquad[i].result<<")"<<endl;}运行结果:。

(完整word版)计算机编译原理名词解释_总结版

(完整word版)计算机编译原理名词解释_总结版

2.二义性文法:如果一个文法存在某个句子对应两棵不同的语法树,则称这个文法是二义性文法。

5.最左推导:任何一步α=>β都是对α中的最右非终结符替换。

6.语法:一组规则,用它可形成和产生一组合式的程序。

7.文法:描述语言的语法结构的形式规则。

8.基本块:指程序中一顺序执行的语句序列,其中只有一个入口和一个出口,入口就是其中的第一个语句,出口就是其中的最后一个语句。

10.短语:令G 是一个文法,S 划文法的开始符号,假定αβδ是文法G 的一个句型,如果有S αAδ且A β,则称β是句型αβδ相对非终结符A 的短语。

12.规范句型:由规范推导所得到的句型。

13.扫描器:执行词法分析的程序。

15.句柄:一个句型的最左直接短语。

16.语法制导翻译:在语法分析过程中,根据每个产生式所对应的语义程序进行翻译的方法 叫做语法制导翻译。

18.素短语:素短语是指这样一个短语,至少含有一个终结符,并且,除它自身外不再含任何更小的素短语。

20.语义:定义程序的意义的一组规则。

三种级别:局部优化、循环优化、全局优化21.词法分析词法分析的主要任务是从左向右扫描每行源程序的符号,按照词法规则从构成源程序的字符串中识别出一个个具有独立意义的最小语法单位,并转换成统一的内部表示(token),送给语法分析程序。

23.语法树句子的树结构表示法称为语法树(语法分析树或语法推导树)。

给定文法G=(V N ,V T ,P ,S),对于G 的任何句型都能构造与之关联的语法树。

这棵树具有下列特征:(1)根节点的标记是开始符号S 。

(2)每个节点的标记都是V 中的一个符号。

(3)若一棵子树的根节点为A ,且其所有直接子孙的标记从左向右的排列次序为A 1A 2…A R ,那么A →A 1A 2…A R 一定是P 中的一条产生式。

(4)若一标记为A 的节点至少有一个除它以外的子孙,则A ∈V N 。

(5)若树的所有叶节点上的标记从左到右排列为字符串w ,则w 是文法G 的句型;若w 中仅含终结符号,则w 为文法G 所产生的句子。

编译原理中的目标代码生成与优化

编译原理中的目标代码生成与优化

编译原理中的目标代码生成与优化编译原理是计算机科学中的一门重要课程,它研究的是将高级程序语言转化为机器语言的过程。

目标代码生成与优化是编译过程中的两个关键环节,本文将就这两个方面展开讨论。

一、目标代码生成目标代码生成是编译过程中的最后一步,它的任务是将中间代码转化为能够在目标机器上执行的机器代码。

目标代码生成的质量直接影响程序的执行效率和占用的存储空间。

1. 寄存器分配在进行目标代码生成之前,我们需要进行寄存器分配。

寄存器分配的目的是将中间代码中的临时变量分配到机器寄存器中,减少内存读写操作,提高程序的运行速度。

常用的寄存器分配算法有线性扫描算法和图着色法。

2. 目标代码生成技术目标代码生成的技术有很多,下面列举几种常见的技术:(1) 直接生成代码:直接将中间代码翻译为目标机器的指令序列。

这种方法简单直接,但生成的目标代码质量一般较低。

(2) 间接生成代码:先将中间代码翻译为一个中间形式,再将中间形式转化为目标机器的指令序列。

这种方法可以进行一些优化,生成的目标代码质量较高。

(3) 使用代码模板:事先定义一些目标机器的指令模板,并根据中间代码的特征选择合适的指令模板来生成目标代码。

这种方法可以充分利用目标机器的特性,生成的目标代码效率较高。

二、目标代码优化目标代码优化是指对生成的目标代码进行一系列的优化,以提高程序的运行效率和减少代码的空间占用。

1. 基本块优化基本块是由顺序执行的指令组成的,没有前驱指令和后继指令的指令序列。

基本块优化的目的是对基本块中的指令进行优化,以减少执行时间和空间开销。

常见的基本块优化技术有死代码删除、常量传播等。

2. 寄存器优化寄存器是计算机中的一块高速存储器,能够提供快速的数据访问速度。

寄存器优化的目的是将变量尽可能地存放在寄存器中,以减少内存读写操作,提高程序的执行效率。

常用的寄存器优化技术有寄存器分配、寄存器重命名等。

3. 循环优化循环是程序中的重要结构之一,对循环进行优化可以显著提高程序的执行效率。

编译原理课件-代码优化

编译原理课件-代码优化

Wensheng Li BUPT @ 2008
常數合併的實現
在符號表中增加兩個資訊域
–標誌域:指示當前是否存在與該變數相關的常數。 –常數域:如果常數存在,則該域存放的即是與該變數相
應的當前常數值。
常數合併時,注意事項:
–不能將結合律與交換律用於浮點運算式,因為浮點運算 的精度有限,這兩條定律並非是恒真的。
PI:=3.14; D-to-R:= 30P.I01/4117/814084.00;.0
i:=0 10: i:=i+1
... if i<10 goto 10
i:=0 10: i:=0+1
... if i<10 goto 10
... a[i]:=9.0 ... a[j]:=3.0 b:=a[i]
?
7/62
– 所謂等價,指不改變程式的運行結果 – 所謂有效,指目標代碼運行時間短、佔用空間少
基本塊的dag是一種結點上有標記的有向非迴圈圖
– 葉結點由變數名字或常量標記。 – 根據作用到名字上的算符,決定需要名字的左值還是右
值。大多數葉結點代表右值。 – 葉結點代表名字的初值,通常為識別字加上腳標0。 – 內部結點由運算符號標記,代表計算出來的值。 – 圖中各結點可能附加一個或多個識別字,表示這些識別
10.1 優化概述
代碼優化程式的任務
–將前端產生的中間代碼轉換為等價的目標代碼
代碼優化程式的要求
–等價變換 –提高目標代碼的執行速度 –減少目標代碼佔用的空間
代碼優化程式的地位
–目標代碼生成之前的中間代碼優化 –目標代碼生成之後的目標代碼優化
3/62
Wensheng Li BUPT @ 2008
代碼優化程式的位置

编译原理之中间代码生产、词法优化与代码生成

编译原理之中间代码生产、词法优化与代码生成

编译原理之中间代码⽣产、词法优化与代码⽣成
中间代码⽣成
在把⼀个源程序翻译成⽬标代码的过程中,⼀个编译器可能构造出⼀个或多个中间表⽰。

这些中间表⽰可以有多种形式。

语法树是⼀种中间表⽰形式,它们通常在语法分析和语义分析中使⽤。

在源程序的语法分析和语义分析完成之后,很多编译器⽣成⼀个明确的低级的或类机器语⾔的中间表⽰。

我们可以把这个表⽰看作是某个抽象机器的程序。

该中间表⽰应该具有两个重要的性质:它应该易于⽣成,且能够被轻松地翻译为⽬标机器上的语⾔。

代码优化
机器⽆关的代码优化步骤试图改进中间代码,以便⽣成更好的⽬标代码。

“更好”通常意味着更快,但是也可能会有其他⽬标,如更短的或能耗更低的⽬标代码
代码⽣成
代码⽣成器以源程序的中间表⽰形式作为输⼊,并把它映射到⽬标语⾔。

如果⽬标语⾔是机器代码,那么就必须为程序使⽤的每个变量选择寄存器或内存位置。

然后,中间指令被翻译成为能够完成相同任务的机器指令序列。

代码⽣成的⼀个⾄关重要的⽅⾯是合理分配寄存器以存放变量的值。

(这⾥我觉得还存疑因为书本上下下段还说了⼀句话,上⾯对代码⽣成的讨论忽略了对源程序中的标识⾏进⾏存储分配的重要问题。

) 不过总之,运⾏时刻的存储组织⽅法依赖于被编译的语⾔。

编译器在中间代码⽣成或代码⽣成阶段做出有关存储分配的决定。

编译原理 代码优化

编译原理 代码优化
(4) 3型四元式:有三个后继结点, 如图5–1(6)。
16
第5章 代码优化
说明:对于3型四元式,对于数组赋值的情形需
特殊考虑,暂不讨论。对四元式(7)也不涉及,下面仅 讨论含0、1、2型四元式的基本块的DAG构造算法。
规定:用大写字母(如A、B等)表示四元式中的变
量名(或常数);用函数Node(A)表示A在DAG中的相应 结点,其值记为n(用n表示DAG中的一个结点值)或者 无定义(未命名或未加标记)。
17
第5章 代码优化
仅含0、1、2型四元式的基本块DAG构造算 法分别描述如下(算法开始前, DAG为空):
形如“A=B”的0型四元式的构造算法
(1) 若 Node(B) 无定义,则构造一标记为B的叶结点并 定义为Node(B) ,并记 Node(B) 的值为n。
(2) 若 Node(A) 无定义,则把A附加在结点 n 上,即 令Node(A)= n;否则,先从Node(A)的附加标识符集 中将A删去(注意: 若Node(A)是叶结点, 则不能将A删 去),然后再把A附加到新结点n上,并令Node(A)=n。
由于在构造DAG的同时已作了局部优化, 所以最后所得到的是优化过的四元式序列。
15
第5章 代码优化
为了DAG构造算法的需要,将图5–1中的四 元式按照其对应结点的后继结点个数分为四类:
(1) 0型四元式:后继结点个数为0, 如图5–1(1); (2) 1型四元式:有一个后继结点, 如图5–1(2); (3) 2型四元式:有两个后继结点,如图5–1(3)(4)(5);
(1)若 Node(B) 无定义,则构造一标记为 B 的叶结点,并定义为
Node(B);如果Node(C)无定义,则构造一标记为C的叶结点,并

编译原理 第十章 代码优化

编译原理 第十章  代码优化

第十章代码优化某些编译程序在中间代码或目标代码生成之后要对生成的代码进行优化。

所谓优化,实质上是对代码进行等价变换,使得变换后的代码运行结果与变换前代码运行结果相同,而运行速度加大或占用存储空间少,或两者都有。

优化可在编译的不同阶段进行,对同一阶段,涉及的程序范围也不同,在同一范围内,可进行多种优化。

一般,优化工作阶段可在中间代码生成之后和(或)目标代码生成之后进行。

中间代码的优化是对中间代码进行等价变换。

目标代码的优化是在目标代码生成之后进行的,因为生成的目标代码对应于具体的计算机,因此,这一类优化在很大程度上依赖于具体的机器,我们不做详细讨论。

另外依据优化所涉及的程序范围,又可分为局部优化、循环优化和全局优化三个不同的级别。

局部优化指的是在只有一个入口、一个出口的基本程序块上进行的优化。

循环优化对循环中的代码进行的优化。

全局优化是在整个程序范围内进行的优化。

本章重点:局部优化基本块的DAG表示第一节优化技术简介为了说明问题,我们来看下面这个例子,源程序是:P :=0For I :=1 to 20 doP :=P+A[I]*B[I];经过编译得到的中间代码如图10-1-1所示,这个程序段由B1和B2两个部分组成,B2是一个循环,假定机器按字节编址。

那么,对于这个中间代码段,可进行如下这些优化。

1、删除多余运算(删除公共子表达式)优化的目的在于使目标代码执行速度较快。

图10-1-1中间代码(3)和(6)中都有4*I的运算,而从(3)到(6)没有对I赋值,显然,两次计算机的值是相等的。

所以,(6)的运算是多余的。

我们可以把(6)变换成:T4 :=T1。

这种优化称为删除多余运算或称为删除公共子表达式。

2、代码外提减少循环中代码总数的一个重要办法是代码外提。

这种变换把循环不变运算,即其结果独立于循环执行次数的表达式,提到循环的前面。

使之只在循环外计算一次,上例中,我们可以把(4)和(7)提到循环外。

经过删除多余运算和代码外提后,代码变成图10-1-2。

(完整word版)编译原理复习题

(完整word版)编译原理复习题

《编译原理》常见题型一、填空题1、编译程序的工作过程一般可以划分为词法分析,语法分析,语义分析,中间代码生成,目标代码生成等几个基本阶段。

2、若源程序是用高级语言编写的,目标程序是机器语言程序或汇编程序,则其翻译程序称为编译程序。

3、编译方式与解释方式的根本区别在于是否生成目标代码。

5、对编译程序而言,输入数据是源程序,输出结果是目标程序。

7、若源程序是用高级语言编写的,目标程序是机器语言程序或汇编程序,则其翻译程序称为编译程序。

8、一个典型的编译程序中,不仅包括词法分析、语法分析、中间代码生成、代码优化、目标代码生成等五个部分,还应包括表格处理和出错处理。

其中,词法分析器用于识别单词。

10、一个上下文无关文法所含四个组成部分是一组终结符号、一组非终结符号、一个开始符号、一组产生式。

12、产生式是用于定义语法成分的一种书写规则。

13、设G[S]是给定文法,则由文法G所定义的语言L(G)可描述为L(G)={x│S*x,x∈V T*} 。

14、设G是一个给定的文法,S是文法的开始符号,如果S*⇒x(其中x∈V*),则称x是文法的一个句型。

15、设G是一个给定的文法,S是文法的开始符号,如果S*⇒x (其中x∈V T*),则称x是文法的一个句子。

16、扫描器的任务是从源程序中识别出一个个单词符号。

17、语法分析最常用的两类方法是自上而下和自下而上分析法。

18、语法分析的任务是识别给定的终结符串是否为给定文法的句子。

19、递归下降法不允许任一非终结符是直接左递归的。

20、自顶向下的语法分析方法的关键是如何选择候选式的问题。

21、递归下降分析法是自顶向下分析方法。

22、自顶向下的语法分析方法的基本思想是:从文法的开始符号开始,根据给定的输入串并按照文法的产生式一步一步的向下进行直接推导,试图推导出文法的句子,使之与给定的输入串匹配。

23、自底向上的语法分析方法的基本思想是:从给定的终结符串开始,根据文法的规则一步一步的向上进行直接归约,试图归约到文法的开始符号。

编译原理-中间代码优化

编译原理-中间代码优化
/* Global variables */
/********************************************************************/
Four *fhead;
DagNode*nhead;
std::list<DagNode*>list_Dag;
vector<string>input_source;
input_source.push_back("*,2,T0,T3");
input_source.push_back("+,R,r,T4");
input_source.push_back("*,T3,T4,T5");
input_source.push_back("-,R,r,T6");
input_source.push_back("*,T5,T6,B");
/* Deceleration of structures */
/********************************************************************/
structFour{
string op;//操作符
string arg1;//第一个操作数
string arg2;//第二个操作数
break;
case1:
tmp1->bsf=fhead->arg1;
tmp1->var= "";
tmp1->flag = 0;
tmp1->lchild= NULL;
tmp1->rchild= NULL;

编译原理6中间代码优化

编译原理6中间代码优化

参见下页四元式表
6
7>删除无用赋值 (2) 和 (6) 两四元式为无用 四元式,可以删除. 最终优化后, 得到下页四元式表
(1) PROD:=0 (2) I:=1 (4) T2:=addr(A)-4 (7) T5:=addr(B)-4 (3) T1:=4 (5) T3:=T2[T1] (6) T4:=T1 (8) T6:=T5[T1] (9) T7:=T3*T6 (10) PROD:=PROD+T7 (3’) T1:=T1+4 (12) if T1<=80 goto(5)
(1) PROD:=0 (2) I:=1 (4) T2:=addr(A)-4 (7) T5:=addr(B)-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 (3’) T1:=T1+4 (12) if I<=20 goto(5)
9
基本块划分算法: 1) 求四元式程序中所有基本入口四元式,包括:
a) 程序的第一条四元式;
b) 转移语句转移到的四元式;
c) 条件语句之后的第一条四元式.
2) 对每一入口四元式,构造一个基本块: 从该入口四元式到下一入口四元式之前的一条四元式, 或到一转移语句,或到一停止语句之间的四元式序列 组成. 3) 凡未纳入这些基本块的四元式,为无用四元式,可以删除.
10
示例:
设四元式程序如下:
(1) read (X) (2) read (Y) (3) R:=X MOD Y (4) if R=0 goto (8) (5) X:=Y (6) Y:=R (7) goto (3) (8) write (Y) (9) halt

(完整word版)编译原理 基础试题

(完整word版)编译原理 基础试题
1.计算机高级语言翻译成低级语言只有解释一种方式。(×)
2.在编译中进行语法检查的目的是为了发现程序中所有错误。(×)
4.正则文法其产生式为A->a,A->Bb, A,B∈VN,a、b∈VT。(×)
5.每个文法都能改写为LL(1)文法。(√)
6.递归下降法允许任一非终极符是直接左递归的。(√)
7.算符优先关系表不一定存在对应的优先函数。(×)
E→T∣E+T
T→F∣T﹡F
F→a∣(E)
该文法句型E+F﹡(E+T)的简单短语是下列符号串中的__B___。
①(E+T)②E+T③F④F﹡(E+T)
A.( )①和③B.( )②和③C.( )③和④D.( )③
6.若一个文法是递归的,则它所产生的语言的句子___A__。
A.( )是无穷多个B.( )是有穷多个
C.( )是可枚举的D.( )个数是常量
7.词法分析器用于识别__C___。
A.( )句子B.( )句型C.( )单词D.( )产生式
8.在语法分析处理中,FIRST集合、FOLLOW集合、SELECT集合均是_B____。
A. ( )非终极符集B.()终极符集C.( )字母表D. ( )状态集
9.在自底向上的语法分析方法中,分析的关键是___D__。
3.一个句型中的最左____B_称为该句型的句柄。
A.( )短语B.()简单短语C.( )素短语D.( )终结符号
4.设G是一个给定的文法,S是文法的开始符号,如果S->x(其中x∈V*),则称x是文法G的一个__B___。
A.( )候选式B.( )句型C.( )单词D.( )产生式
5.文法G[E]:
A.( )模拟执行器B.( )解释器

编译原理 代码优化

编译原理 代码优化

B6 t11 := 4 * i x := a[t11] t13 := 4 * n t14 := a[t13]
a[t11] := t14 a[t13] := x
•优化举例
公共子表达式删除-基本块间
t2:=4 * i : B2 -- B5
t4:= 4 * j : B3 -- B5
B5 t6 := 4 * i x := a[t6] t8 := 4 * j t9 := a[t8] a[t6] := t9 a[t8] := x goto B2
•优化举例
快速排序程序片段如下, i = m 1; j = n; v = a[n]; while (1) { do i = i +1; while(a[i]<v);
do j =j 1;while (a[j]>v); if (i >= j) break;
x=a[i]; a[i]=a[j]; a[j]=x; }
- 代码外提 - 归纳变量删除 - 强度削弱
例:while (i <= limit 2 ) …
变换成 t = limit 2; //为什么提出循环? while (i <= t ) …
•优化举例
强度削弱和归纳变量删除
j和t4的值步伐一致地变化 这样的变量叫做归纳变量
在循环中有多个归纳变量时, 也许只需要留下一个 这个操作由归纳变量删除 过程来完成
do j =j 1;while (a[j]>v); if (i >= j) break;
x=a[i]; a[i]=a[j]; a[j]=x; }
x=a[i]; a[i]=a[n]; a[n]=x;
//B4 (13) if i >= j goto (23)

编译原理与技术之代码优化共48页文档

编译原理与技术之代码优化共48页文档

1
0















谢谢!
36、自己的鞋子,自己知道紧在哪里。——西班牙
37、我们唯一不会改正的缺点是软弱。——拉罗什福科
xiexie! 38、我这个人走得很慢,但是我从不后退。——亚伯拉罕·林肯
39、勿问成功的秘诀为何,且尽全力做你应该做的事吧。——美华纳
40、学而不思则罔,思而不学则殆。——孔子
文 家 。汉 族 ,东 晋 浔阳 柴桑 人 (今 江西 九江 ) 。曾 做过 几 年小 官, 后辞 官 回家 ,从 此 隐居 ,田 园生 活 是陶 渊明 诗 的主 要题 材, 相 关作 品有 《饮 酒 》 、 《 归 园 田 居 》 、 《 桃花 源 记 》 、 《 五 柳先 生 传 》 、 《 归 去来 兮 辞 》 等 。
编译原理与技术之代码优化
6













7、翩翩新 来燕,双双入我庐 ,先巢故尚在,相 将还旧居。
8













9、 陶渊 明( 约 365年 —427年 ),字 元亮, (又 一说名 潜,字 渊明 )号五 柳先生 ,私 谥“靖 节散

编译原理 第九章 中间代码优化

编译原理 第九章 中间代码优化

第九章中间代码优化提高源程序的运行速度,需要几个阶段的优化:其第一步是由用户对源程序一级进行优化;第二步是由编译器的前端对于中间代码进行优化;第三步是编译器的后端对于目标代码进行优化。

中间代码的优化是独立于目标机的优化,因此具有通用性和易移植性。

可以说,在构造编译器时最花费时间的部分是优化部分。

带优化的编译器对源程序的优化开销较大,因此,如何优化和优化到什么程度是必须要考虑的问题。

与优化有密切关联的一种说法是程序的“90 / 10规律”,其意思是说执行程序的90%时间是花在程序的10%上。

上述规律指明了优化的重点要花在那个10%上。

9.1 引言9.1.1 优化目标和要求优化的最终目标是提高目标代码的运行速度,而好的优化能大幅度地提高运行速度,因此所有编译器都有优化部分,但优化要花费很多时间,因此做哪些优化不做哪些优化是有一定讲究的。

优化要绝对保证正确性。

优化是一种变换,而且是包含大量代码移动的非结构化复杂变换,因此稍微不留心就很容易出错。

正因为这样特别要强调正确性的绝对保证。

所谓绝对保证正确性是指对于相同的输入,输出与源程序同样的结果。

优化要得到一定数量级的提高。

优化对象有多种,每种优化都会得到一些效果,但所得效果可能差别很大。

如果一个编译器把优化重点放在效果不大的方面,那么不能得到好的结果。

实际上,最重要的优化对象是循环内下标变量地址的计算,而它的实现需要常表达式节省、公共表达式节省和不变表达式的循环外提等优化。

优化要适度。

目前的编译器并不是什么都加以优化,比如,假设有函数调用f(1,2,3),则应能算出一个常数,但它要求执行函数体,而此时还没有目标代码,因此不能当时计算。

当然这不等于说不能进行优化,主要是开销太大。

9.1.2 优化的必要性读者可能提出如果用户写出好程序,那么优化可能是没有必要的。

事实并非如此,其主要原因有以下几方面:一是受到高级语言能力的限制;二是源程序可能是由其他系统自动生成的;三是在中间代码生成阶段产生出很多明显可优化的部分。

第09章 中间代码优化

第09章 中间代码优化
《编译原理》电子教案
7
韶关学院计算机系程细柱
kill_c(Bi)可以确定 def_c(Bi) 和kill_c(Bi)可以确定 out_c(Bi)= (in_c(Bi) – kill_c(Bi)) ∪ def_c(Bi) in_c(Bi)= ∩j∈pre(i) out_c(Bj) 应用in_c(Bi)可以对Bi进行常量表达式优化。 in_c(Bi)可以对Bi进行常量表达式优化 应用in_c(Bi)可以对Bi进行常量表达式优化。 常表达式全局优化原理: 常表达式全局优化原理: 对每一基本块Bi求出in_c(Bi)集合, Bi求出in_c(Bi)集合 对每一基本块Bi求出in_c(Bi)集合, 其中in_c(B 为空; 其中in_c(B0)为空; in_c(Bi)代替基本块Bi的ConstDef; 代替基本块Bi 用in_c(Bi)代替基本块Bi的ConstDef; 优化过程同局部常表达式优化原理, 优化过程同局部常表达式优化原理,
《编译原理》电子教案 ( ASSIGN, t2, Y)
4
B6:( LABEL, L6) Y,t3 (ADDI, X, Y,t3 ) (GT, t3, 0, t4 ) (JUMP0 (JUMP0, t4, L8) B7:( SUBI, X, 1,t5 ) ,t5 ( ASSIGN, t5, X ) ( JUMP, L6 ) B8:( LABEL, L8 ) ( ASSIGN, 0, Z ) ( STOP )
《编译原理》电子教案
11
韶关学院计算机系程细柱
实例: 实例: =D+C× =D+C× =D+C× D:=D+C×B; A:=D+C×B; C:=D+C×B; A:=D+C×B; =D+C×
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验三中间的代码优化
某些编译程序在中间代码或目标代码生产之后要对其进行优化,所谓优化就是对代码进行等价的变换。

而变换后的代码运行结果与变换前的代码运行结果相同。

而运行速度加快或占用内存空间减少。

中间的代码优化就是对中间代码进行等价的变换。

基本块的有向图DAG(Directed Acyclic Graph)
有向图中任何一条通路都不是环路,则称该有向图为无环路有向图,简称为DAG。

一、实验题目:
中间代码的局部优化
二、实验目的:
掌握局部优化方法、提高机器的运行速度
三、实验内容:
1 、构造基本块内的优化DAG
假设:(1)ni 为已知结点号,n为新结点号;
(2)访问各结点信息时,按结点号逆序排序
2、完成对下例三类表达式的优化
(1)常值表达式的优化
(2)公共表达式的优化
(3)无用赋值的优化
3、输出根据优化的DAG重组四元式
四、设计概要:
首先要实现表达式中间代码生成,采用递归下降子程序法实现。

E→T{ω0 “push(SYN,w)”T“QUAT” }
T→F{ω1”push(SYN,w)”F“QUAT”}
F→i“push(SEM,entry(w))”|(E)
其中:·push(SYN,w)---当前单词w入符号栈SYN;
·push(SEM,entry(w))--- 当前i在符号表中的入口值压入语义栈SEM;·QUAT---生成四元式函数
①T:=newtemp;
②QT[j]=(SYN[k],SEM[s-1],SEM[s],T);j++;
③ pop(SYN,_);pop(SEM,_);pop(SEM,_); push(SEM,T);
在对中间代码进行局部优化
五、程序代码及运行结果:
1.表达式中间代码生成
#include<iostream>
#include<cstdlib>
using namespace std;
char str[50];
char sem[50];
char syn[50];
char ch;
int i=0;
int j=0;
int n=0;
int p=1;
void push_sem(char w)
{
sem[j++]=w;
}
void push_syn(char w)
{
syn[n++]=w;
}
void Gen()
{
char s[2][2];
char w;
w=sem[--j];
if(w>='1'&&w<='9')
{
s[0][1]=w;
s[0][0]=sem[--j];
}
else
{
s[0][0]=w;
s[0][1]=' ';
}
w=sem[--j];
if(w>='1'&&w<='9')
{
s[1][1]=w;
s[1][0]=sem[--j];
}
else
{
s[1][0]=w;
s[1][1]=' ';
}
cout<<"("<<syn[--n]<<","<<s[1][0]<<s[1][1]<<","<<s[0][0]<<s[0][1] <<","<<'t'<<p++<<")"<<endl;
push_sem('t');
push_sem(p+47);
}
int F()
{
int m;
int E();
if(ch=='(')
{
ch=str[i++];
m=E();
if(ch==')') ch=str[i++];
else
{
//cout<<"表达式error!"<<endl;
return 0;
}
}
else
{
if((ch>='a'&&ch<='z')||(ch>='1'&&ch<='9'))
{
push_sem(ch);
ch=str[i++];
}
else
{
//cout<<"表达式error!"<<endl;
return 0;
}
}
return 1;
}
int T()
{
int k,m,l;
k=F();
if(k==0){return 0;}
while(1)
{
//push_syn(ch);
if(ch=='*')
{
push_syn(ch);
ch=str[i++];
m=F();
if(m==0){return 0;}
Gen();
}
else if(ch=='/')
{
push_syn(ch);
ch=str[i++];
l=F();
if(l==0){return 0;}
Gen();
}
else break;
}
return 1;
}
int E()
{
int k,m,l;
k=T();
if(k==0){return 0;}
while(1)
{
//push_syn(ch);
if(ch=='+')
{
push_syn(ch);
ch=str[i++];
m=T();
if(m==0){return 0;}
Gen();
}
else if(ch=='-')
{
push_syn(ch);
ch=str[i++];
l=T();
if(l==0){return 0;}
Gen();
}
else break;
}
return 1;
}
int main()
{
int k,q=0;
char w1,w2,w;
char s[1][2];
cout<<"输入表达式(以'#'结束):";
cin>>str;
w1=str[i++];
w2=str[i++];
if(w2!='=') {i=i-2;q=1;}
ch=str[i++];
k=E();
if(q==0)
{
w=sem[--j];
if(w>='1'&&w<='9')
{
s[0][1]=w;
s[0][0]=sem[--j];
}
else
{
s[0][0]=w;
s[0][1]=' ';
}
cout<<"("<<w2<<","<<s[0][0]<<s[0][1]<<","<<" "<<","<<w1<<")"<<endl;
}
if(k==0) cout<<"error!"<<endl;
else
{
if(ch=='#') cout<<"OK!"<<endl;
else cout<<"error!"<<endl;。

相关文档
最新文档