编译原理语法分析.docx

上传人:b****7 文档编号:9027009 上传时间:2023-02-02 格式:DOCX 页数:17 大小:20.10KB
下载 相关 举报
编译原理语法分析.docx_第1页
第1页 / 共17页
编译原理语法分析.docx_第2页
第2页 / 共17页
编译原理语法分析.docx_第3页
第3页 / 共17页
编译原理语法分析.docx_第4页
第4页 / 共17页
编译原理语法分析.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

编译原理语法分析.docx

《编译原理语法分析.docx》由会员分享,可在线阅读,更多相关《编译原理语法分析.docx(17页珍藏版)》请在冰豆网上搜索。

编译原理语法分析.docx

编译原理语法分析

实验三  中间代码生成

一.实验目的与要求:

1.掌握语法制导进行语义分析的基本方法。

2.中间代码的几种形式(后缀式,三元式,四元式,抽象语法树和DAG图)。

3.掌握简单表达式,多维下标变量、原子语句、结构语句、声明的中间代码结构。

4.用LR分析法处理表达式(简单的表达式)。

二.实验内容:

给出一表达式的后缀式,借助于语义信息找semstack(数组实现)输出其四元式,假设此表达式只含常量或变量,不含函数的调用。

三、主要算法如下:

1、此方法处理的要点:

A.当读出常量C时,产生常量的内部表示将类型和值Arg(c)压入语义信息栈中。

B.当读出变量id时,产生变量的内部表示,将其类型和内部地址压入语义信息栈。

C.当碰到运算符w时,从栈顶出两个元素即sem[top]和sem[top-1],产生中间代码Gencode,并从栈顶删除这两个元素,将此中间代码的结果的临时变量的类型和临时变量的地址入栈。

D.重复上述工作,直到扫描完整个表达式。

2、产生中间代码的Gencode过程,工作如下:

1.若sem[top-1].Type≠sem[top].Type,且sem[top-1].Type=integer则结果为实型real,并且为左分量即sem[top-1]产生类型转换代码。

则结果为实型real,并且为左分量产生类型转换代码。

2.若sem[top-1].Type≠sem[top].Type,且sem[top].Type=integer则结果为实型real并且为右分量即sem[top]产生类型转换代码。

3.若sem([op-1].Type=sem[top].Type,则结果类型为sem[top].Type不产生类型转换。

4.产生(w,sem[top-1],sem[top],temp)中间代码。

5.删除左右分量的栈单元,把结果的类型和临时变量地址入栈。

四、实验代码:

  

#include

#include

#include

typedefstruct{

charname[10];

chartype;

}sem,*ptsem;

typedefstruct{

ptsem*base;

intutop;

  }stack;

inti=1;

intj=0;

intn=0;

stacklist;

charst[10],str1[10],*p;

ptsemyylist=newsem[10];

voidpop(ptsem&pt)

   {

     pt=list.base[list.utop--];

     return;

     }

voidgencode(ptsemtop,ptsemsubtop,charw)

{

ptsempt=newsem;

   if(top->type==subtop->type){}

   elseif(top->type!

='r')

    {

      printf("(FLOAT,%s,t%d);\n",top->name,i);

      charc=i+48;

      top->name[0]='t';

      top->name[1]=c;

      top->name[2]='\0';

      top->type='r';

      i++;

    }

else

  {

    printf("(FLOAT,%s,t%d);\n",subtop->name,i);

    charc=i+48;

    subtop->name[0]='t';

    subtop->name[1]=c;

    subtop->name[2]='\0';

    subtop->type='r';

    i++;

   }

  printf("(%c,%s,%s,t%d);\n",w,subtop->name,top->name,i);

  charc=i+48;

  pt->type=top->type;

  pt->name[0]='t';

  pt->name[1]=c;

  pt->name[2]='\0';

  i++;

  push(pt);

  return;

  }

voididentify()

{

while(*p>='a'&&*p<='z')

     st[j++]=*p++;

st[j]='\0';

j=0;

intflag=0;

if(!

strcmp(st,"float")||!

strcmp(st,"int"))flag=1;

if(flag==1){strcpy(str1,st);return;}

sempp;

if(!

strcmp(str1,"float"))

{

  strcpy(pp.name,st);

  pp.type='r';

  }

if(!

strcmp(str1,"int"))

{

  strcpy(pp.name,st);

  pp.type='i';

  }

yylist[n++]=pp;

}

voidconid()

{

ptsempt=newsem;

intflag=0,k=0;

do

{

  pt->name[k++]=*p;

  if(*p++=='.')flag=1;

}while(*p>='0'&&*p<='9'||*p=='.');

pt->type=flag?

'r':

'i';

if(*p>'9'&&*p<'0')

{printf("theconstdatayouinputediswrong");

exit(0);

}

   pt->name[k]='\0';

   push(pt);

}

voidmain()

{

  initlist();

  printf("\n");

  charstr[100];

gets(str);

  p=str;

  while(*p!

='\0')

{

  if(!

(*p>='a'&&*p<='z'||*p>='A'&&*p<='Z'||*p==';'||*p==''||*p==','))

  {printf("thisdefineiswrong!

");exit(0);}

switch(*p){

     case',':

p++;break;

     case'':

p++;break;

     case';':

p++;break;

     default:

identify();

}

}

charstrpds[100];

gets(strpds);

p=strpds;

charch=*p,a;

ptsemtop,subtop;

while(*p!

='\0'){

     if(ch>='0'&&ch<='9')a='0';

  elseif(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')a='1';

  elseif(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='^')a='2';

  elseif(ch==';')break;

  elseif(ch=='')a='4';

     elsea='3';

switch(a){

case'0':

conid();ch=*p;break;

case'1':

varid();ch=*p;break;

case'2':

pop(top);pop(subtop);gencode(top,subtop,ch);ch=*++p;break;

case'3':

printf("%cisaillegalletter!

\n",ch);exit(0);

case'4':

ch=*++p;

   }

}

if(*++p!

='\0')

printf("thissetenseisillegal!

");

}

实验四中间代码优化

一.实验的目的和要求:

1.掌握中间代码优化的目标和要求及优化的必要性。

2.掌握几种优化方法及优化能到什么程度。

3.实现一种简单的中间代码优化常量表达式的局部优化。

二、基本块上常量表达式的局部优化的主要算法如下:

1.设置一张常量表consdef(空),其元素是二元组(Var,Val),Var是变量名或常量名,Val是它们的值。

2.读当前文件中的四元式tuple。

3.对tuple中的分量去查常量表,若有则用其值去代换,得到新的newtuple。

4.若新的四元式newtuple是(w,A,B,T)情形,若A,B都是常量,则计算AwB的值V,并在consdef表中填入(T,V),同时删除本四元式,即不把此四元式写入输出文件中,否则将新的四元式输入输出文件中。

5.若newtuple是(Assign,A,B)情形,若A是常量,则把(B,A)填入consdef表,(若有B项,则只需改值),若A是变量,但consdef中有B则删除此项。

6.重复上述步骤,直到输入文件结束。

三、实验代码:

structconsdef

    {charvar;

      intval;}

voidmain()

{FILE*cfptr;

FILE*cfpt;

charstring[100][100];

char*w;

charr[10];

charstring1='\n';

structconsdefvaltable[100];

for(i=0;i<10;i++)

   {valtable[i].val=0;

      valtable[i].var='';

   }                         //初始化consdef

if((cfptr=fopen("wsq.txt","r+"))==NULL)

    printf("Filecouldnotbeopened\n");

else

  while(!

feof(cfptr))

     {fscanf(cfptr,"%s",string[i]);

      }//读取文件中的内容并将其存入到数组中

fclose(cfptr);

for(i=0;i

  {while(string[i][m]!

=',')

{w[m-1]=string[i][m];

  }//取tuple的逗号前的3字符串并将其存入到w中

   for(into=m-1;o<10;o++)

    if(!

strcmp(w,"assig    ")&&isdigit(string[i][m]-'\0')&&!

(isdigit(string[i][m+2])))

{valtable[e].val=string[i][m];

   valtable[e].var=string[i][m+2];

}  //若该tuple是赋值语句且第一个是数字第二个是变量

   if(!

(isdigit(string[i][m]-'\0')))//若第一个是变量则查consdef表

{  for(intp=0;p

    if(valtable[p].var==string[i][m])//若consdef中有该变量,则改变tuple为newtuple并设置标志v

       {string[i][m]=valtable[p].val;

  }

if(v)    {if(isdigit(string[i][m]-'\0')&&isdigit(string[i][m+2]-'\0'))

{  if(!

strcmp(w,"addi     "))//若该语句是加运算

    {valtable[e].var=string[i][m+4];

     string[i][m+4]=string[i][m]+string[i][m+2]-48;

     valtable[e].val=string[i][m+4];

     e++;

     string[i][0]='#';

     }

  if(!

strcmp(w,"subi     "))  //若该语句是减运算

    {valtable[e].var=string[i][m+4];

     string[i][m+4]=string[i][m]-string[i][m+2]+48;

     valtable[e].val=string[i][m+4];

     string[i][0]='#';

     }

  

  if(!

strcmp(w,"divi     "))   //若该语句是除运算

    {valtable[e].var=string[i][m+4];

     string[i][m+4]=(string[i][m]-48)/(string[i][m+2]-48)+48;

     valtable[e].val=string[i][m+4];

     string[i][0]='#';

     }

      }

     if(!

strcmp(w,"assig    ")&&isdigit(string[i][m]-'\0'))

   {valtable[e].val=string[i][m];

    valtable[e].var=string[i][m+2];

      }

}

   }

if((cfptr=fopen("wsq1.txt","w"))==NULL)//将优化后的tuple存入文件wsq1.txt中

    printf("Filecouldnotbeopened\n");

else

  for(i=0;i

     {  if(string[i][0]!

='#')

{  fprintf(cfptr,"%s",string[i]);

     fprintf(cfptr,"%c",string1);

  }

      }

}

华东理工大学信息学院计算机系

2010年12月16日

一.  实验序号

    实验3

二.  实验题目

中间代码生成

三.  实验日期

2010.12.16-2010.12.23

四.  实验环境(操作系统,开发语言)

操作系统是Windows

开发语言是VisualC++2003语言

五.  实验内容(实验要求)

(a) 在VisualC++2003中创建项目:

“VisualC++项目”/“Win32”(Win32控制台项目)

(b) 输入下面“六.C语言源程序”一节中的C语言语句。

(c) 点击菜单“调试”/“逐语句”(F11)。

(d) 点击菜单“调试”/“窗口”/“反汇编”,观察C语言语句相应的汇编代码并仔细阅读分析和理解所有的汇编代码。

(e) 填写下面“七.汇编代码” 一节中的空白,并在右边的注释处写出你填空的依据(注意:

“七.汇编代码”中的地址也许与你的计算机中观察到的地址有些偏差,请根据“七.汇编代码”中显示的代码的地址进行填写和说明)。

六.  C语言源程序

int_tmain(intargc,_TCHAR*argv[])

{

       int           nWeigh,nMiles,nLong,nDiscount,Price[10],i,nFee;

       nWeigh=10;

       nMiles=5;

       nLong=0;

       if(nMiles>10)

              nLong=1;

       if(nLong==1&&nWeigh>50)

              nDiscount=4;

       else

       if(nLong==1&&nWeigh>40)

              nDiscount=3;

       else

       if(nLong==1&&nWeigh>30)

              nDiscount=2;

       else

              nDiscount=1;

       for(i=0;i<10;i++)

              Price[i]=i*20;

       i=0;

       nFee=0;

       while(i

       {

              nFee=nFee+Price[i];

              i++;

       }

       switch(nDiscount)

       {

       case1:

    nFee=nFee+100;

                     break;

       case2:

    nFee=nFee+80;

                     break;

       case3:

    nFee=nFee+40;

       case4:

    nFee=nFee+10;

                     break;

       default:

   nFee=200;

       }

       return0;

}

 

七.  汇编代码

00411A10      push                     ebp 

00411A11      mov               ebp,esp

00411A13      sub                esp,13Ch

00411A19      push                     ebx 

00411A1A     push                     esi 

00411A1B     push                     edi 

00411A1C     lea                 edi,[ebp-13Ch]

00411A22      mov               ecx,4Fh

00411A27      mov               eax,0CCCCCCCCh

00411A2C     repstos          dwordptr[edi]

 

00411A2E      mov               dwordptr[nWeigh],0Ah

00411A35      mov               dwordptr[nMiles],5

00411A3C     mov               dwordptr[nLong],0

 

00411A43      cmp               dwordptr[nMiles],0Ah

00411A47      jle                  main+40h(411A50)// 如果小于等于的话就跳到下一个if语句             

00411A49      mov               dwordptr[nLong],1

 

00411A50      cmp               dwordptr[nLong],1

00411A54      jne       main+55h(411A65h)//如果nLong不等于1就直接跳到下一个if语句              

00411A56      cmp               dwordptr[nWeigh],32h

00411A5A     jle                  main+55h(411A65h)

00411A5C     mov               dwordptr[nDiscount],4

00411A63      jmp        main+86h(411A96h)//  直接跳到for循环             

 

00411A65      cmp               dwordptr[nLong],1

00411A69      jne                 main+6Ah(411A7Ah)

00411A6B     cmp               dwordptr[nWeigh],28h

00411A6F      jle                  main+6Ah(411A7Ah)

00411A71      mov               dwordptr[nDiscount],3

00411A78      jmp            main+86h(411A96h) //  直接跳到for循环               

 

00411A7A     cmp               dwordptr[nLong],1

00411A7E      jne       main+7Fh(411A8Fh) // 如果nLong不等于1,就给nDiscount赋值1              

00411A80      cmp               dwordptr[nWeigh],1Eh

00411A84      jle                  main+7Fh(411A8Fh) //  如果nWeigh小于等于30,就给nDiscount赋值为1             

00411A86      mov               dwordptr[nDiscount],2

00411A8D     jmp                main+86h(411A96h)

00411A8F      mov               dwordptr[nDiscount],1

 

00411A96      mov               dwordptr[i],0

00411A9D     jmp                main+98h(411AA8h)//直接跳到i与10比较的语句               

00411A9F      mov               eax,dwordptr[i]

00411AA2     add                eax,1

00411AA5     mov               dwordptr[i],eax

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 高中教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1