精华内容
下载资源
问答
  • 中间代码生成实验报告
    2021-05-20 17:37:33

    《中间代码生成实验报告》由会员分享,可在线阅读,更多相关《中间代码生成实验报告(16页珍藏版)》请在人人文库网上搜索。

    1、一 、 实验目的通过在实验二的基础上,增加中间代码生成部分,使程序能够对实验二中的识别出的赋值语句,if语句和while语句进行语义分析,生成四元式中间代码。二 、 实验方法实验程序由c语言完成,在Turboc 2.0环境中调试通过。语义分析程序的基本做法是对文法中的每个产生式分别编写一个语义分析子程序,当程序语法部分进行推倒或规约时,就分别调用各自的语义分析程序。当语法分析结束时,语义分析也就结束了。在本实验程序中,当语法分析部分识别出语法正确的句子时,就进入content函数(当语法分析识别出不正确的句子时,不进入content函数,也就是不进行语义分析),然后根据句子的类型进行分类,进入。

    2、不同的语义处理部分。对于赋值语句,关键是产生正确的处理算术表达式E的四元式。程序中的ec函数的功能就是产生算术表达式的四元式,在ec函数中使用了两个栈idshed,opshed,分别是算术表达式的数据栈和符号栈。每次提取一个数字和一个算符,然后将算符与与栈顶算符进行优先级比较,优先级高则将单前数字和算符进栈,低或者相等的话则将当前栈顶元素进行合并,产生四元式。直至整个算术表达式结束。其中还有一些细节问题,具体的做法可以参看程序。对于实验给定的if语句的文法格式,条件判断式C只中可能是或者89+56*67 then f:=7*7+4;ff:=6+6*6-6%4+8; if sl+78*7689*。

    3、56+67 then while a-798+45*45 do f:=7*7+4;. 四 、 运行结果首先对测试程序进行语法分析,识别出正确的句子,当识别出正确的句子时,就对当前句子进行语义分析,而语法不正确的句子不进行语义分析。ff:=6+6*6- Error(4):Except ID or NUM ; Error(2):Syntax error if sl89+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。

    4、 (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*7689*56+67 then while a-798+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, 。

    5、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 五 、 实验小结终于完成了编译原理的三次实验,这几次实验使我们更彻底地巩固了编译原理。从詷法分析到语法分析直到这次的中间代码都是看似简单的基础知识,却花了不少时间对课本多次反复研究、请教学习,进行深层次地探讨才找。

    6、出编程时出现的种种问题。还有很多程序方面很细节的问题,很容易被突略,却往往又是关键。总地来说,虽然实验做得很辛苦,但真的可以从实验当中学习到很多,认识到很多。并对编译理解也透彻了许多,比较清晰地掌握了编译程序的原理和方法。附录:#include#include#include#define reser 20char *charstring=abcdefghijklmnopqrstuvwxyz;char *numstring=0123456789;char *strstring=abcdefghijklmnopqrstuvwxyz0123456789;char reservereser10;ch。

    7、ar idshed4010,opshed4010;char token15,id15,sym15;char line80,tempp240;char ch,ch1,temp,tem;char tx10;char tn4,signt120,signt220,ju20;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 filename15;FILE *fp;void getch()if(li=。

    8、0) if (cc=ii)cc=1; ii=0;if (row1=1) fseek(fp,-1,1); /*读行首字符将指针退回一格,若是整个文本的开头,则不需要*/line0=fgetc(fp);row1=1;while(temp=fgetc(fp)!=n) & (temp!=EOF) linecc=temp;cc+;tempppp=temp;pp+;linecc= ; /*将缓冲带后加上一个空字符,以便行和行之间号区分 */cc+;tempppp= ;pp+;while(temp=fgetc(fp)=n) & (temp!=EOF); /* 跳过空行*/linecc=0;tem=linei。

    9、i;ii+;ch=tem;elsech=tempppp;pp+;void getnbc()getch();while (ch= )getch();if (ch=)dogetch();while( ch=);getnbc();void retract()ii-;void ret()pp-;int jchar(char ch) /* 判断ch是不是字母 */if(strchr(charstring,ch)=0)return 0;else return 1;int jnum(char ch) /* 判断ch是不是数字 */if(strchr(numstring,ch)=0)return 0;else。

    10、 return 1;int jstr(char ch) /* 判断ch是不是字母或数字 */if(strchr(strstring,ch)=0)return 0;else return 1;void advance()getnbc();kind=0;if (jchar(ch)=1)k=0;do if(k15) tokenk=ch; k+;getch(); while(jstr(ch)=1);if (li=0)retract();else ret();tokenk=0; /*截去token中的无用字符*/strcpy(id,token);for(t =0;t=20;t+)if(strcmp(re。

    11、servet,id)=0)break;if ( t=20 ) kind=t ;else kind=21;strcpy(sym,id);elseif (jnum(ch)=1)k=0;doif ( k15 ) tokenk=ch; k+;getch();while( jstr(ch)=1);if (li=0)retract();else ret();kind=22;tokenk=0;strcpy(sym,token);elseif(ch=.) kind=26;k=0;dosymk= ; k+;while(k!=15);sym0=ch;sym1=0;void error(int n)judge=0; /*出错退出,将judge0*/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( E* 次数:1357533 已用完,请联系开发者。

    更多相关内容
  • 中间代码生成实验报告.doc
  • 编译原理语义分析和中间代码生成实验报告,基于VS2010开发的纯C#的程序,附程序执行截图
  • 完整的编译原理实验报告 关于语法、语义和词法分析器三部分的 很全哦 一、实验题目 表达式中间代码生成 二、实验目的 熟悉算术表达式的语法分析与中间代码生成原理。 三、实验内容 1. 构造算术表达式的四元式翻译...
  • c语言中间代码生成器 输入——算术表达式; 输出——语法分析结果及相应的四元式序列
  • 编译原理实验4:中间代码生成实验
  • 熟悉算术表达式的语法分析与中间代码生成原理 二、实验内容 1. 构造算术表达式的四元式翻译文法 2. 设计算术表达式的递归下降子程序分析算法 3. 设计算术表达的四元式生成算法 4. 实现代码并调试运行 三、实验...
  • (1) 设计语法制导翻译生成表达式的四元式的算法; (2) 编写代码并上机调试运行通过。 ·输入——算术表达式 ·输出——语法分析结果 相应的四元式序列 (3) 本实验已给出递归子程序法的四元式属性翻译文法的设计,...
  • 编制程序,完成局部优化过程中的基本块划分。给定一段代码,判定程序的入口语句,划分基本块,删除无用产生式和冗余节点。
  • 分析中间代码生成程序 含PL0程序,源代码综合性实验报告 分析PL/0编译程序的总体结构、代码生成的方法和过程;具体写出一条语句的中间代码生成过程。
  • 中间代码生成

    2018-06-21 14:53:52
    中间代码生成.zip,中间代码生成,file_out.txt,中间代码生成.cpp,中间代码生成.exe,中间代码生成.docx
  • 文章目录1 实验目的和内容1.1 实验目的1.2 实验内容...(1)通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析 所识别的语法范畴变换为某种中间代码的语义翻译方法。 (2)掌握目前普遍采用的语义分析方法─

    1 实验目的和内容

    1.1 实验目的

    (1)通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析 所识别的语法范畴变换为某种中间代码的语义翻译方法。

    (2)掌握目前普遍采用的语义分析方法──语法制导翻译技术。

    (3)给出 PL/0 文法规范,要求在语法分析程序中添加语义处理,对于语法正确的表达式,输出其中间代码;对于语法正确的算术表达式,输出其计算值。

    1.2 实验内容

    已给 PL/0 语言文法,在实验二或实验三的表达式语法分析程序里,添加语义处理部分,输出表达式的中间代码,用四元式序列表示。

    1.3 实验要求

    (1)语义分析对象重点考虑经过语法分析后已是正确的语法范畴,本实 验重点是语义子程序。

    (2)在实验二或实验三“语法分析器”的里面添加 PL/0 语言“表达式”部分的语义处理,输出表达式的中间代码,计算表达式的语义值。

    (3)中间代码用四元式序列表示。

    2 设计思想

    2.1 语义规则

    属性计算的过程即是语义处理的过程对于文法的每一个产生式配备一组属性的计算规则,则称为语义规则。

    (1)终结符只有综合属性,它由词法分析器提供。

    (2)非终结符既可以有综合属性也可以有继承属性,文法开始符号的所有继承属性作为属性计算前的初始值。

    (3)产生式右边符号的继承属性和产生式左边符号的综合属性都必须提供一个计算规则。

    (4)产生式左边符号的继承属性和产生式右边符号的综合属性由其它产生式的属性规则计算。

    2.2 递归下降翻译器

    递归下降分析法的原理是利用函数之间的递归调用来模拟语法树自上而下的构建过程。从根节点出发,自顶向下为输入串中寻找一个最左匹配序列,建立一棵语法树。对于每个非终结符的继承属性当作形式参数,函数的返回值当作非终结符的继承属性;对于终结符要初始化所有的继承属性。再进行分析过程中,非终结符根据当前的输入符号决定使用哪个产生式候选。

    2.3 递归下降子程序伪代码

    (1)表达式

    function表达式:string;
    string s1, s2, s3, result;
    BEGIN
      IF SYM=+’ OR SYM=-’ THEN
      ADVANCE;
      ELSE IF SYM =FIRST() 
      ELSE ERROR;
      BEGIN s1:=;
      END;
      WHILE SYM=+’ OR SYM=-’ THEN
      BEGIN
        ADVANCE;
        S2:=;
        result := newtemp();
        emit(SYM,s1,s2,result);
        s1:= result;
      END;
      Return result;
    END;
    

    (2)项

    function 项:string;
    string s1, s2, s3, result;
    BEGIN
      IF SYM =FIRST(因子) THEN
      BEGIN
        s1:=因子;
      END;
      ELSE ERROR;
      WHILE SYM =*’OR SYM=/’ THEN
    IF SYM =FIRST(因子) THEN 
      BEGIN 
        ADVANCE;
        S2:=因子;
        result := newtemp();
        emit(SYM,s1,s2,result);
        s1:= result;
      END;
      Return result;
    END;
    ELSE ERROR;
    

    (3)因子

    function 因子:string;
    string s;
    BEGIN
      IF SYM =(’ THEN
      ADVANCE;
      s:=表达式;
    ADVANCE; 
      IF SYM=)’ THEN
      ADVANCE;
    Return s; 
    ELSE ERROR; 
      ELSE IF SYM =FIRST(因子) THEN
    ADVANCE;
      ELSE ERROR;
    END;
    

    3 算法流程

    算法流程图如下所示,首先输入表达式,然后进行词法分析,把词法分析的结果存在结构体中,之后调用递归下降分析器中的表达式子程序进行分析,最后得到四元组并存在相应的结构体中,下一步进行判断,如果是算术表达式,就计算该算术表达式的值并输出,如果不是算术表达式,就不做处理,直接输出四元组,最后判断程序的输入是否结束,如果没有结束,就再次输入表达式,重复上述步骤,如果结束,则程序退出。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fM7peODy-1634978806002)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps7B8D.tmp.jpg)]

    图1 算法流程图

    4 源程序

    #include<iostream>
    #include<stdlib.h>
    #include<stdio.h>
    #include<string.h>
    using namespace std; 
    
    //存储词法分析的结果
    struct cf_tv
    {
      string t;  //词法分析的类型
      string v;  //词法分析变量的值
    };
    
    //存储四元组
    struct qua
    {
      string symbal;  //符号
      string op_a;   //第一个操作数
      string op_b;   //第二个操作数
      string result;  //结果
    };
    
    string input; //全局输入
    int cnt;    //全局变量
    int k=0;    //tv输入
    int ljw=0;
    cf_tv result[200]; //存放结果
    qua output[200];  //存放输出的四元组
    int x=0;      //qua 的下标
    int ans=0;     //遍历的时候的下标
    bool error=true;  //出错标志
    int is_letter=0;
    int t[1001];    //临时存放空间
    string item();
    string factor();
    
    //产生新变量名t1,t2等
    string new_temp()
    {
      char *pq;
      char mm[18];
      pq=(char*)malloc(18);
      ljw++;
      //转换成字符串格式
      snprintf(mm,sizeof(mm),"%d",ljw);
      strcpy(pq+1,mm);
      pq[0]='t';
      string s;
      s=pq;
      return s;
    }
    
    //判断是否和目标串匹配
    bool judge (string input, string s)
    {
      if (input.length()!=s.length()) return false;
      else
      {
        for(unsigned int i=0;i<s.length();i++)
        {
          if(input[i]!=s[i]) return false;  //遍历
        }
        return true;
      }
    }
    
    //判断是否和目标串匹配
    bool judge1 (string input, string s)
    {
      if(input[0]==s[0]) return true;
      else return false;
    }
    
    //判断非符号的程序,包含判断关键字,标识符,常数
    void not_fh(string p)
    {
      //判断是否跟目标串相同,相同的话输出结果
      if(judge (p,"begin"))
         {
           result[k].t="beginsym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"call"))
         {
           result[k].t="callsym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"const"))
         {
           result[k].t="constsym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"do"))
         {
           result[k].t="dosym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"end"))
         {
           result[k].t="endsym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"if"))
         {
           result[k].t="ifsym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"odd"))
         {
           result[k].t="oddsym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"procedure"))
         {
           result[k].t="proceduresym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"read"))
         {
           result[k].t="readsym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"var"))
         {
           result[k].t="varsym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"then"))
         {
           result[k].t="thensym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"write"))
         {
           result[k].t="writesym";
           result[k].v=p;
           k++;
         }
         //判断是否跟目标串相同,相同的话输出结果
         else if(judge (p,"while"))
         {
           result[k].t="whilesym";
           result[k].v=p;
           k++;
         }
         else
         {
           int flag = 0;
           for(unsigned int i=0;i<p.length();i++)
           {
             //判断是否是标识符
             if(!isdigit(p[i]))
             {
               flag = 1;
               result[k].t="ident";
               result[k].v=p;
               k++;
               break;
             }
           }
           //判断是否是数字
           if(!flag)
           {
             result[k].t="number";
             result[k].v=p;
             k++;
           }
         }
    }
    
    //防止多个运算符组成,返回正确下标
    int change(string str,int cnt)
    {
      int y=0;
      char fh[15]={'+','-','*','/','=','<','>',':','(',')',',',';','.'};
      for(int i=0;i<13;i++)
      {
        if(str[cnt]==fh[i])
        {
          y=i;
        }
      }
      if(y==5)
      {
        //如果运算符是两个符号组成,cnt+1
        if(str[cnt+1]=='>')
        {
          cnt=cnt+1;
          return cnt;
        }
        //判断两个运算符相连
        else if(str[cnt+1]=='=')
        {
          cnt=cnt+1;
          return cnt;
        }
      }
      //判断:=
      if(y==7)
      {
        cnt=cnt+1;
        return cnt;
      }
      return cnt;
    }
    
    //对运算符和界符的输出
    void fh_1(string str,int cnt)
    {
      int y=0;
      char fh[15]={'+','-','*','/','=','<','>',':','(',')',',',';','.'};
      for(int i=0;i<13;i++)
      {
        if(str[cnt]==fh[i]) y=i;
      }
      //plus
      if(y==0)
      {
         result[k].t="plus";
         result[k].v=fh[y];
         k++;
      }
      //minus
      if(y==1)
      {
         result[k].t="minus";
         result[k].v=fh[y];
         k++;
      }
      //times
      if(y==2)
      {
         result[k].t="times";
         result[k].v=fh[y];
         k++;
      }
      //slash
      if(y==3)
      {
         result[k].t="slash";
         result[k].v=fh[y];
         k++;
      }
      //eql
      if(y==4)
      {
         result[k].t="eql";
         result[k].v=fh[y];
         k++;
      }
      if(y==5)
      {
        //neq
        if(str[cnt+1]=='>')
        {
          cnt=cnt+1;
          result[k].t="neq";
          result[k].v="<>";
          k++;
        }
        //leq
        else if(str[cnt+1]=='=')
        {
           result[k].t="leq";
           result[k].v="<=";
           k++;
        }
        //lss
        else
        {
           result[k].t="lss";
           result[k].v="<";
           k++;
        }
      }
      if(y==6)
      {
        //geq
        if(str[cnt+1]=='=')
        {
           result[k].t="geq";
           result[k].v=">=";
           k++;
        }
        //gtr
        else
        {
           result[k].t="gtr";
           result[k].v=">";
           k++;
        }
      }
      //becomes
      if(y==7)
      {
        result[k].t="becomes";
        result[k].v=":=";
        k++;
      }
      //lparen
      if(y==8)
      {
        result[k].t="lparen";
        result[k].v="(";
        k++;
      }
      //rparen
      if(y==9)
      {
        result[k].t="rparen";
        result[k].v=")";
        k++;
      }
      //comma
      if(y==10)
      {
        result[k].t="comma";
        result[k].v=",";
        k++;
      }
      //semicolon
      if(y==11)
      {
        result[k].t="semicolon";
        result[k].v=";";
        k++;
      }
      //period
      if(y==12)
      {
        result[k].t="period";
        result[k].v=".";
        k++;
      }
    }
    
    //词法分析
    void cifa()
    {
      string str;
      while(cin>>str)
      {
        cnt=0;
        const char *d = " +-*/=<>:(),;.";
        char *p;
        //运用空格和运算符和界符分割字符串并且遍历
        char buf[1001] ;
        //字符串转成数组
        strcpy(buf , str.c_str());
        //p是一个char*
        p = strtok(buf,d);
        while(p)
        {
          //当前无符号
          if(str[cnt]==p[0])
          {
             not_fh(p);
             cnt=cnt+strlen(p);
          }
          //当前是符号
          else
          {
            while(str[cnt]!=p[0])
            {
              fh_1(str,cnt);
              cnt=change(str,cnt);
              cnt=cnt+1;
            }
            not_fh(p);
            cnt=cnt+strlen(p);
          }
          //下移一位,进行遍历
          p=strtok(NULL,d);
        }
        for(unsigned int i=cnt;i<str.length();i++)
        {
          //防止最后有多个符号
          fh_1(str,i);
        }
      }
    }
    
    //判断是哪种类型的计算
    void judge_type()
    {
      for(int i=0;i<k;i++)
      {
        if(judge(result[i].t,"ident"))
        {
          is_letter=1;
          break;
        }
      }
    }
    
    //表达式的递归下降分析函数
    string bds()
    {
      string s;
      string s1,s2,s3;
      if(ans>k) return NULL;
      //加减符号
      if(judge(result[ans].v,"+") || judge(result[ans].v,"-"))
      {
        ans++;
        if(ans>k)
        {
          cout<<1<<endl;
          //error
          error=false;
        }
        s1=item();
      }
      else if( judge(result[ans].v,"(") ||judge(result[ans].t,"ident") ||judge(result[ans].t,"number"))
      {
        //项目判定,前面条件是first集合
        s1=item();
      }
      else
      {
        cout<<2<<endl;
        //error
        error=false;
      }//
      while(judge(result[ans].v,"+") || judge(result[ans].v,"-"))
      {
        int ans_temp=ans;
        ans++;
        if(ans>k)
        {
          cout<<3<<endl;
          //error
          error=false;
        }
        //项目循环
        s2=item();
        output[x].symbal=result[ans_temp].v;
        output[x].op_a=s1;
        output[x].op_b=s2;
        output[x].result=new_temp();
        s=output[x].result;
        s1=s;
        x++;
      }
      return s;
    }
    
    //项的递归下降分析函数
    string item()
    {
      string s;
      string s1,s2,s3;
      if(ans>k) return NULL;
      //因子判断
      s1=factor();
      while(judge(result[ans].v,"*") || judge(result[ans].v,"/"))
      {
        int ans_temp=ans;
        ans++;
        if(ans>k)
        {
          cout<<4<<endl;
          //error
          error=false;
        }
        s2=factor();
        output[x].op_a=s1;
        output[x].symbal=result[ans_temp].v;
        output[x].op_b=s2;
        output[x].result=new_temp();
        s=output[x].result;
        s1=s;
        x++;
      }
      return s1;
    }
    
    //因子的递归下降分析函数
    string factor()
    {
      string s;
      if(ans>=k) return NULL;
      //开头字母或数字
      if(judge(result[ans].t,"ident") ||judge(result[ans].t,"number"))
      {
        s=result[ans].v;
        ans++;
        if(ans>k)
        {
          cout<<5<<endl;
          //error
          error=false;
        }
      }
      //左括号
      else if(judge(result[ans].v,"("))
      {
        ans++;
        //表达式
        s = bds();
        //右括号
        if(judge(result[ans].v,")"))
        {
         ans++;
         if(ans>k)
         {
           cout<<6<<endl;
           //error
           error=false;
         }
        }
      }
      else
      {
        cout<<7<<endl;
        //error
        error=false;
      }
      return s;
    }
    
    //删除第一个字母
    string del(string s)
    {
      char c[101];
      for(unsigned int i=0;i<s.length()-1;i++)
      {
        c[i]=s[i+1];
      }
      return c;
    }
    
    void js(int i)
    {
      char* end;
      //如果是乘法
      if(judge(output[i].symbal,"*"))
      {
        //判断第一个符号是字母还是数字
        if(!judge1(output[i].op_a,"t"))
        {
          if(!judge1(output[i].op_b,"t"))
          {
            //强制类型转换
            t[i+1]=static_cast<int>(strtol(output[i].op_a.c_str(),&end,10))*static_cast<int>(strtol(output[i].op_b.c_str(),&end,10));
          }
        }
      }
      else
      {
        if(!judge1(output[i].op_b,"t"))
        {
          string ss;
          ss=del(output[i].op_a);
          //强制类型转换
          int z=static_cast<int>(strtol(ss.c_str(),&end,10));
          t[i+1]=t[z]*static_cast<int>(strtol(output[i].op_b.c_str(),&end,10));
        }
        else
        {
          string s;
          s=del(output[i].op_a);
          int yy=static_cast<int>(strtol(s.c_str(),&end,10));
          string ss;
          ss=del(output[i].op_b);
          int zz=static_cast<int>(strtol(ss.c_str(),&end,10));
          t[i+1]=t[yy]*t[zz];
        }
      if(judge(output[i].symbal,"+"))
      {
        if(!judge1(output[i].op_a,"t"))
        {
          if(!judge1(output[i].op_b,"t"))
          {
            t[i+1]=static_cast<int>(strtol(output[i].op_a.c_str(),&end,10))+static_cast<int>(strtol(output[i].op_b.c_str(),&end,10));
          }
          else
          {
            string ss;
            ss=del(output[i].op_b);
            int yy=static_cast<int>(strtol(output[i].op_a.c_str(),&end,10));
            int zz=static_cast<int>(strtol(ss.c_str(),&end,10));
            t[i+1]=yy+t[zz];
          }
        }
        else
        {
          if(!judge1(output[i].op_b,"t"))
          {
            string ss;
            ss=del(output[i].op_a);
            int zz=static_cast<int>(strtol(ss.c_str(),&end,10));
            t[i+1]=t[zz]+static_cast<int>(strtol(output[i].op_b.c_str(),&end,10));
          }
          else
          {
            string s;
            s=del(output[i].op_a);
            int yy=static_cast<int>(strtol(s.c_str(),&end,10));
            string ss;
            ss=del(output[i].op_b);
            int zz=static_cast<int>(strtol(ss.c_str(),&end,10));
            t[i+1]=t[yy]+t[zz];
          }
        }
      }
     }
    }
    
    int main()
    {
      //词法分析函数
      cifa();
      //判断类型
      judge_type();
      //语法分析和语义分析
      bds();
      //进行输出
      if(is_letter==1)
      {
         for(int i=0;i<x;i++)
        {
          cout<<"("<<output[i].symbal<<","<<output[i].op_a<<","<<output[i].op_b<<","<<output[i].result<<")"<<endl;
        }
      }
      //进行输出,计算结果
      else
      {
        for(int i=0;i<x;i++)
        {
          js(i);
        }
        cout<<t[x]<<endl;
      }
      return 0;
    }
    

    5 调试数据

    5.1 测试样例一

    【样例输入】
    2+3*5
    
    【样例输出】
    17
    

    样例一结果如下所示

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RjiL6KMD-1634978806011)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps7C1B.tmp.jpg)]

    图2 样例一测试结果

    5.2 测试样例二

    【样例输入】
    2+3*5+7
    
    【样例输出】
    24
    

    样例二结果如下所示

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OdYoOdcP-1634978806014)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps7C2C.tmp.jpg)]

    图3 样例二测试结果

    5.3 测试样例三

    【样例输入】
    a*(b+c) 
    
    【样例输出】
    (+,b,c,t1)
    (*,a,t1,t2)
    

    样例三结果如下所示

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ElSTqE0-1634978806025)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps7C2D.tmp.jpg)]

    图4 样例三测试结果

    5.4 测试样例四

    【样例输入】
    a*(b+c)+d
    
    【样例输出】
    (+,b,c,t1)
    (*,a,t1,t2)
    (+,t2,d,t3)
    

    样例四结果如下所示

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3TAgwESy-1634978806030)(file:///C:\Users\User\AppData\Local\Temp\ksohtml\wps7C2E.tmp.jpg)]
    图5 样例四测试结果

    6 实验调试情况及体会

    6.1 实验调试情况

    由上一步中的四个测试样例可以得到,所有的测试样例均得到了相应的输出结果,说明代码编写成功,并且在代码中设置了出错处理,以便解决其他情况。

    6.2 实验体会

    这次实验在上课之前及时的进行了预习,在编写代码之前需要写出递归下降翻译器的伪代码,重点就是要找到对于每个非终结符的属性哪些是继承属性,哪些是综合属性。然后将继承属性作为参数,综合属性作为返回值,进行计算。

    编写代码的时候,需要用到实验一和实验二的代码,写实验一代码的时候没考虑到后面会用到,直接将结果输出并没有保存中间结果,以至于自己在编码的时候需要先将实验一的结果存放在一个自定义的结构体中,里面包含词法分析的两个因素:值和类型。而分析器分析的时候,直接调取这个结构体的内容,四元式的结果也会放在一个特殊的结构体,里面记录了四元式的四个值,方便输出。如果是数字运算式,可以模拟计算器对于这四个值进行计算,并且需要数组和判定运算符函数来判断是数字还是辅助变量,根据对应符号进行运算。

    通过这次实验,从词法分析到语法分析到语义分析的知识点有了大致的回顾,并且重点回顾了每个阶段输入什么,输出什么,这些信息怎么存储,用什么算法来计算。还需要进一步优化自己的代码,比如在这次的实验代码过程中,需要改进的是将词法分析和语法分析合并,降低时间复杂度,提高执行效率。

    通过这四次的实验过程,让我对于编译原理这门课有了比较清晰的认识,可能理论课当时听懂了,过一会可能就会遗忘。通过学习编译原理,感觉用到了数据结构,算法等思维理解,又需要对于许多概念的理解记忆。这也是这门课的难点所在。通过这次学习,懂得更要注重对于基础科目的掌握,不断加强和拓展自己的计算机思维。

    最后感谢刘善梅老师对我一学期的悉心指导,不胜感激,我会继续努力学好接下来的每一门专业课程,不负老师厚望!

    展开全文
  • 2. 分析PL/0程序的Block子程序和Gen子程序,了解代码生成的方法和过程。使用概要算法来描述语句的代码生成过程。 3. 自己编写一个简单的PL/0程序,能够正确通过编译,得到中间代码。列出自己编写的源程序和编译后...
  • 用于编译原理课设 或小作业 很有用的主要是三元式四元式 逆波兰式
  • 编写一个中间代码生成程序,能将算术表达式等翻译成逆波兰、三元组或四元组形式(选择其中一种形式即可)。 2 实验内容 (1)实验要求 将算术表达式等翻译成逆波兰、三元组或四元组形式 (2)输入格式 包含各种算术...

    1 实验任务

    编写一个中间代码生成程序,能将算术表达式等翻译成逆波兰、三元组或四元组形式(选择其中一种形式即可)。

    2 实验内容

    (1)实验要求
    将算术表达式等翻译成逆波兰、三元组或四元组形式
    (2)输入格式
    包含各种算术表达式的文本文件。
    (3)输出格式
    程序能输出生成的逆波兰、三元组或四元组序列。

    3 算法描述

    人们常用的算术表达式是中序表达式,而逆波兰表达式是后续表达式,在计算机编程中,后续表达式更易于求得表达式结果。

    此处实现的算法主要是对栈的应用,主要实现是先给+、-、*、/、(设定优先级,然后读入符号,若是数字则直接压入结果栈,若是左括号则压入符号栈,是右括号则弹结果栈直到遇到左括号。

    其他情况则按优先级压入,若当前符号优先级大于栈顶,直接压入符号栈,否则弹出符号栈到结果栈,直到为空或者符号优先级大于栈顶再压入符号栈。
    而逆波兰表达式的求值则较为简单,每次从结果栈弹出三个值,分别是两个操作数和一个操作符,然后进行运算后压栈,当栈内只剩一个元素时,那个元素往往就是运算结果。

    对于出错处理部分,将它们分成了三个错误:

    1. 字符非法:通过遍历字符看起是否合法实现。
    2. 操作符连续:维护一个bool的变量记录上个字符是否代表操作符。
    3. 括号无法匹配:利用一个栈。若左括号就压栈,右括号时查看是否是左括号处于栈顶,是的话就弹栈,不是的话就出错。最后,如果这个栈有剩余的左括号,说明出错。

    4 代码

    主要包含四个函数:

    • Convert:将输入的中序表达式转化为结果栈的形式(这里用链表模拟栈)。
    • GetRes:以Convert的输出做输入,求得后序表达式的值。
    • CheckInput:查看输入是否有错误。
    • error:输出对应错误。
    //将中序表达式转化为后序表达式
    //并利用后序表达式计算结果
    #include<iostream>
    #include<list>
    #include<cstdio>
    #include<string.h>
    #include<string>
    #include<map>
    using namespace std;
    
    list<string> ope;			//运算符栈
    list<string> res;			//结果栈
    map<string,int> oper;		//存储算符优先级
    list<int> container;		//运算栈
    char invalidChar;
    bool valid = true;
    void error(int x){
    	valid = false;
    	switch(x){
    		case 1://)(()
    			cout<<"非法字符"<<invalidChar<<endl;
    			break;
    		case 2:
    			cout<<"连续的操作符"<<invalidChar<<endl;
    			break;
    		case 3:
    			cout<<"无法匹配括号"<<endl;
    			break;
    	}
    	
    }
    
    void CheckInput(string s){
    	list<char> bracketStack;
    	bool lastOp = true;//记录上一个是否为运算符 
    	for(int i = 0;i<s.length();i++){
    		if(s[i]>='0'&&s[i]<='9'){
    			lastOp = false;
    		}
    		else if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'){
    			if(lastOp){
    				invalidChar=s[i];
    				error(2);
    			}
    			lastOp=true;
    		}
    		else if(s[i]=='('){
    			bracketStack.push_back('(');
    			lastOp=true;//左括号后不能直接出现运算符 
    		}
    		else if(s[i]==')'){
    			if(bracketStack.empty()||bracketStack.back()!='('){//不匹配 
    				error(3);
    			}
    			else{
    				bracketStack.pop_back();
    			}
    			
    		}
    		else{ 
    			lastOp = false;
    			invalidChar=s[i];
    			error(1);
    		}
    		
    	}
    	if(!bracketStack.empty())
    		error(3);
    }
    
    string Convert(char s[])
    {
    	oper["+"] = 1;		//运算符优先级越低,oper越低
    	oper["-"] = 1;
    	oper["*"] = 2;
    	oper["/"] = 2;
    	oper["("] = 0;
    	int i = 0;
    	while(true)
    	{
    		if (i >= strlen(s)) 
    			break;
    		while (s[i]==' '||s[i]=='/t')//去除无效的空格
    			++i;
    		if(s[i]>='0'&&s[i]<='9')	//若为数字则获取
    		{
    			string num;
    			while (s[i] >= '0'&&s[i] <= '9')
    				num.push_back(s[i++]);			
    			res.push_back(num);		//数字直接压入结果栈
    			continue;
    		}
    		else if(s[i]=='(')
    			ope.push_back("(");
    		else if(s[i]==')')			//是右括号则匹配
    		{
    			while(true)
    			{
    				if(ope.back()=="(")
    				{
    					ope.pop_back();
    					break;
    				}
    				res.push_back(ope.back());
    				ope.pop_back();
    			}
    		}
    		else
    		{
    			string num;
    			num.push_back(s[i]);
    			while(!ope.empty())
    			{
    				if(oper[num]>oper[ope.back()])//当前符号优先级大于栈顶,直接压入符号栈
    				{
    				   ope.push_back(num);
    				   break;
    				}
    				res.push_back(ope.back());//否则弹出符号栈到结果栈,直到为空或者符号优先级大于栈顶再压入符号栈。
    				ope.pop_back();
    			}
    			if(ope.empty())
    				ope.push_back(num);
    		}
    		++i;
    	}
    	while(!ope.empty())//最后把符号栈的全部内容弹到结果栈
    	{
    		res.push_back(ope.back());
    		ope.pop_back();
    	}
       string result = "";
       while(!res.empty())//输出后序表达式
       {
          result+=res.front()+" ";
          res.pop_front();
       }
       return result;
    }
    
    int GetRes(string s)
    {
       int res;
       int i = 0;
       while(true)
       {
    		if (i >= s.length()-1) 
    		{
    			break;
    		}
    		while (s[i]==' '||s[i]=='/t')//去除无效的空格
    			++i;
    		if(s[i]>='0'&&s[i]<='9')
    		{
    			int num=0;
    			while (s[i] >= '0'&&s[i] <= '9')
    				num = num*10 + s[i++]-'0';
    			container.push_back(num);
    			continue;
    		}
          else
          {
             int b = container.back();
             container.pop_back();
             int a = container.back();
             container.pop_back();
             int c;
             if(s[i]=='+')
                c = a+b;
             else if(s[i]=='-')
                c = a-b;
             else if(s[i]=='*')
                c = a*b;
             else if(s[i]=='/')
                c = a/b;
             container.push_back(c);
          }
    	  ++i;
       }
       return container.back();
    }
    
    int main()
    {
       char s[30];
       while (scanf("%s", &s) != EOF) {
    		ope.clear();
    		res.clear();			
    		container.clear();
    		valid = true;
    		CheckInput(s);
    		if(!valid)
    			continue;
    	  	string ansStr = Convert(s);				//把中序的算数表达式
          	cout<<ansStr<<endl;						//输出逆波兰表达式
          	cout<<"算数结果:"<<GetRes(ansStr)<<endl;	//输出算数结果
       }
    }
    //56+8130/(2+67)*8
    //9+1/1-7*2+123+456/123+(98+87)
    //56+(8130/((2+67)-6*5+7)*8)
    //56-+8130/(*2+67)*8
    //~45+a/5
    //5+2)(
    
    

    5 运行结果

    (1)测试一:56+8130/(2+67)8
    在这里插入图片描述
    (2)测试二:9+1/1-7
    2+123+456/123+(98+87)
    在这里插入图片描述
    (3)测试三:56+(8130/((2+67)-6*5+7)*8)
    在这里插入图片描述
    (4)测试四:对三种出错情况进行测试。
    56-+8130/(*2+67)*8触发错误:连续的操作符
    ~45+a/5触发错误:非法字符
    5+2)(触发错误:括号不匹配
    在这里插入图片描述

    展开全文
  • 编译原理的一个实验报告 输出的是四元组 附有完整的实验报告
  • (实验报告模板)实验3:语义分析与中间代码生成.pdf(实验报告模板)实验3:语义分析与中间代码生成.pdf(实验报告模板)实验3:语义分析与中间代码生成.pdf(实验报告模板)实验3:语义分析与中间代码生成.pdf(实验报告...
  • (实验报告模板)实验3:语义分析与中间代码生成.docx(实验报告模板)实验3:语义分析与中间代码生成.docx(实验报告模板)实验3:语义分析与中间代码生成.docx(实验报告模板)实验3:语义分析与中间代码生成.docx(实验...
  • (1)通过上机实验,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法范畴变换为某种中间代码的语义翻译方法。 (2)掌握目前普遍采用的语义分析方法─语法制导翻译技术。 (3)给出 PL/0 文法规范,要求...

    一、实验目的

    (1)通过上机实验,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法范畴变换为某种中间代码的语义翻译方法。
    (2)掌握目前普遍采用的语义分析方法─语法制导翻译技术。
    (3)给出 PL/0 文法规范,要求在语法分析程序中添加语义处理,对于语法正确的表达式,输出其中间代码;对于语法正确的算术表达式,输出其计算值。

    二、实验内容

    (1)语义分析对象重点考虑经过语法分析后已是正确的语法范畴,本实验重点是语义子程序。已给 PL/0 语言文法,在实验二或实验三的表达式语法分析程序里,添加语义处理部分,输出表达式的中间代码,用四元式序列表示。
    (2) PL/0 算术表达式的语义计算:
    PL/0 算术表达式,例如:2+35 作为输入。
    输出: 17
    PL/0 表达式的中间代码表示:
    PL/0 表达式,例如: a
    (b+c)。
    输出: (+,b,c,t1)
    (,a,t1,t2)

    三、设计思想

    1.原理
    属性文法:是在上下文无关文法的基础上为每个文法符号(终结符或非终结符)配备若干个相关的“值”(称为属性)。

    属性:代表与文法符号相关的信息,和变量一样,可以进行计算和传递。

    综合属性:用于“自下而上”传递信息。
    在语法树中,一个结点的综合属性的值,由其子结点的属性值确定。

    S—属性文法:仅仅使用综合属性的属性文法。

    语义规则: 属性计算的过程即是语义处理的过程。对于文法的每一个产生式配备一组属性的计算规则,则称为语义规则。
    (1)终结符只有综合属性,它由词法分析器提供。
    (2)非终结符既可以有综合属性也可以有继承属性,文法开始符号的所有继承属性作为属性计算前的初始值。
    (3)产生式右边符号的继承属性和产生式左边符号的综合属性都必须提供一个计算规则。
    (4)产生式左边符号的继承属性和产生式右边符号的综合属性由其它产生式的属性规则计算。
    一遍扫描的处理方法: 与树遍历的属性计算方法不同,一遍扫描的处理方法是在语法分析的同时计算属性值,而不是语法分析构造语法树之后进行属性的计算,而且无需构造实际的语法树。
    因为一遍扫描的处理方法与语法分析器的相互作用,它与下面两个因素密切相关:
    (1)所采用的语法分析方法。
    (2)属性的计算次序。
    2.基于递归下降翻译器的设计

    递归下降分析法的原理是利用函数之间的递归调用来模拟语法树自上而下的构建过程。从根节点出发,自顶向下为输入串中寻找一个最左匹配序列,建立一棵语法树。对于每个非终结符的继承属性当作形式参数,函数的返回值当作非终结符的继承属性;对于终结符要初始化所有的继承属性。再进行分析过程中,非终结符根据当前的输入符号决定使用哪个产生式候选。
    递归下降分析器的设计实现思想:

    1、对每个非终结符A构造一个函数过程,对A的每个继承属性设置一个形式参数,函数的返回值为A的综合属性(作为记录,或指向记录的一个指针,记录中有若干域,每个属性对应一个域)。
    2、非终结符A 对应的函数过程中,根据当前的输入符号决定哪个产生式候选。
    3、每个产生式对应的代码中,按照从左到右的次序,对于单词符号(终结符),非终结符和语义分析分别做以下的工作。
    (1)对于带有综合属性x的终结符X,把x的值存入为X.x设置的变量中。然后产生一个匹配X的调用,并继续读入一个输入符号。
    (2)对于每个非终结符号B,产生一个右边带有函数调用的赋值语句c=B(b1,b2,…,bk)
    (3)对于语义动作,把动作的代码抄进分析器中,用代表属性的变量来代替对应属性的每一次引用。

    算法原理
    1.设计出每个非终结符的文法识别过程。
    2.将输入数据进行处理,提取出单词的编码。
    3.每一个非终结符对应于一个函数(子过程),非终结符所对应的右侧产生式为函数体;为每个非终结符写识别递归函数。
    4.每遇到一个终结符,则需要判断所输入字符是否与之匹配,若匹配则读取下一个,若不匹配,则进行出错处理。
    5.函数相互调用。

    加入递归下降翻译器子程序伪码:

    表达式递归下降子程序为:

    function表达式:string;
    string s1, s2, s3, result;
    BEGIN
    IF SYM=’+’ OR SYM=’-’ THEN
    ADVANCE;
    ELSE IF SYM =FIRST()
    ELSE ERROR;
    BEGIN
     s1:=;
    END;
    WHILE SYM=’+’ OR SYM=’-’ THEN
    BEGIN
    ADVANCE;
    S2:=;
    result := newtemp();
    emit(SYM,s1,s2,result);
    s1:= result;
    END;
    Return result;
    END;
    

    项递归下降子程序为:

    function 项:string;
    string s1, s2, s3, result;
    BEGIN
    IF SYM =FIRST(因子) THEN
    BEGIN
    s1:=因子;
    END;
    ELSE ERROR;
    WHILE SYM =’’OR SYM=’/’ THEN
    IF SYM =FIRST(因子) THEN
    BEGIN
    ADVANCE;        
    S2:=因子;
    result := newtemp();
    emit(SYM,s1,s2,result);
    s1:= result;
    END;
    Return result;
    END;
    

    因子递归下降子程序为:

    function 因子:string;
    string s;
    BEGIN
    IF SYM =(’ THEN
    ADVANCE;
    s:=表达式;
    ADVANCE;
    IF SYM=)’ THEN
    ADVANCE;
    Return s;
    ELSE ERROR;
    ELSE IF SYM =FIRST(因子) THEN
    ADVANCE;
    ELSE ERROR;
    END;
    

    四、源程序及调试运行结果

    1.源程序代码

    #include <iostream>
    #include<bits/stdc++.h>//万能头文件
    using namespace std;
    pair<string, string> results[50]; // results保存词法分析结果,第一个sring存单词类型,第二个string存单词的值
    int lexI = 0; // results的指针
    void Lexical_Analysis()/*lexI为results的长度,即单词数*/
    {
        string inputs;  // 输入字符串
        cin >> inputs;
        map<string,string> words;//应用map数据结构形成一个string->string的对应
        std::map<string,string>::iterator it;//用来遍历整个对应关系的迭代器
        //对应关系进行初始化,如下只包括了表达式的相关符号
        words["+"]="plus";
        words["-"]="minus";
        words["*"]="times";
        words["/"]="slash";
        words["="]="eql";
        words["("]="lparen";
        words[")"]="rparen";
        int input_size=inputs.length(); //输入字符串的长度
        string word; // 字符识别
        for(int i=0; i<input_size; i++)
        {
            while(inputs[i] == ' ' || inputs[i] == '\n')//若最开始为空格或换行符,则将指针的位置往后移
                i++;
            if(isalpha(inputs[i])){//对标识符和基本字进行识别,调用库函数isalpha()
                word = inputs[i++];
                while(isalpha(inputs[i]) || isdigit(inputs[i]))
                    word += inputs[i++];
                it = words.find(word); // 在map中找到相应的词性,并输出
                if(it != words.end())//判断是不是基本字,若为基本字则进行输出
               results[lexI++] = make_pair(words[word], word);//创建新的pair对象
                else
                    results[lexI++] = make_pair("ident", word);
                i--;
            }
            else if(isdigit(inputs[i])){//判断是不是常数,调用库函数isdigit()
                word=inputs[i++];
                while(isdigit(inputs[i]))
                    word+=inputs[i++];
                results[lexI++] = make_pair("number", word);
                i--;
            }
            // <和<=号
            else if(inputs[i]=='<'){
                word=inputs[i++];
                if(inputs[i]=='>'){
                    word+=inputs[i];
                    results[lexI++] = make_pair(words[word], word);
                }
                else if(inputs[i]=='='){
                    word+=inputs[i];
                    results[lexI++] = make_pair(words[word], word);
                }
                else if(inputs[i]!=' '||!isdigit(inputs[i])||!isalpha(inputs[i])){
                    results[lexI++] = make_pair(words[word], word);
                }
                else
                {
                    cout<<"error!"<<endl;
                }
                i--;
            }
            // >和>=
            else if(inputs[i]=='>'){
                word=inputs[i++];
                if(inputs[i]=='='){
                    word+=inputs[i];
                    results[lexI++] = make_pair(words[word], word);
                }
                else if(inputs[i]!=' '||!isdigit(inputs[i])||!isalpha(inputs[i])){
                    results[lexI++] = make_pair(words[word], word);
                }
                else{
                    cout<<"error!"<<endl;
                }
                i--;
            }
            //:=
            else if(inputs[i]==':'){
                word=inputs[i++];
                if(inputs[i]=='='){
                    word+=inputs[i];
                    results[lexI++] = make_pair(words[word], word);
                }else{
                    cout<<"error!"<<endl;
                }
            }
            else{//其他的基本字
                word=inputs[i];
                it=words.find(word);
                if(it!=words.end()){
                    results[lexI++] = make_pair(words[word], word);
                }else{
                    cout<<"error!"<<endl;
                }
            }
        }
    }
    struct quad{/**四元式的结构体**/
        string result;
        string arg1;
        string arg2;
        string op;
    };
    struct quad quad[50]; // 四元式数组
    int quaI = 0; // 指向四元式的指针
    void emit(string op, string arg1, string arg2, string result)//生成一行四元式
    {
        quad[quaI].op = op;
        quad[quaI].arg1 = arg1;
        quad[quaI].arg2 = arg2;
        quad[quaI].result = result;
        quaI++;
    }
    int i = 1; // 记录当前是t1/t2...t几了
    string newT() //产生新变量名t1,t2等
    {
        stringstream ss;
        ss << i;
        string ti = "t" + ss.str();
        i++;
        return ti;
    }
    /**非算数表达式的递归下降分析及四元式生成**/
    int sym=0; // 指示读入的符号
    void advance()  //用来读入下一个符号
    {
        ++sym;
        if(sym > lexI){
            cout << "sym指针越界!";
            exit(0);
        }
    }
    string E1();
    string F1()/*因子分析*/
    {
        string arg;
        if(results[sym].first == "ident"){  //results的第一个string
            arg = results[sym].second;  //保存到results的第二个string里
            advance();
        }
        else if(results[sym].first == "number"){//如果是无符号整数,最终返回相应的整数
            arg = results[sym].second;
            advance();
    }
     //如果是左括号,则要进行右括号匹配,并判断中间是不是表达式,并得出表达式的值进行返回
        else if(results[sym].first == "lparen"){
            advance();
            arg = E1();
            if(results[sym].first == "rparen"){
                advance();
            }
            else{
                cout << "未能匹配右括号!\n";
                exit(0);
            }
        }
        return arg;
    }
    string T1()/*项分析*/
    {
        string op, arg1, arg2, result;
        arg1 = F1();//通过因子分析得到第一个参数的值
        while(results[sym].first == "times" || results[sym].first == "slash")
      {
            op = results[sym].second;
            advance();
            arg2 = F1();//通过因子分析得到第二个参数的值
            result = newT();//产生中间变量名,相当于对结果进行存储
            emit(op, arg1, arg2, result);//产生四元式,相当于进行乘法或除法运算,得出结果
            arg1 = result;//保存得到的结果
        }
        return arg1;//返回项最终得到的值
    }
    string E1()/*表达式分析*/
    {
        string op, arg1, arg2, result;
        if(results[sym].first == "plus" || results[sym].first == "minus"){
            advance();
        }
        arg1 = T1();//通过项分析得到第一个参数的值
        while(results[sym].first == "plus" || results[sym].first == "minus"){
            op = results[sym].second;
            advance();
            arg2 = T1();
            result = newT();
            emit(op, arg1, arg2, result);
            arg1 = result;
        }
        return arg1;
    }
    /**算数表达式的递归下降分析及四元式生成**/
    int E2();
    int F2()
    {
        int arg=0;
        if(results[sym].first == "ident"){
            cout << "算数表达式含字母,无法计算!\n";
            exit(0);
        }
        else if(results[sym].first == "number"){//如果 是数字,则返回相应的值
            arg = atoi(results[sym].second.c_str());
            advance();
        }
        //如果是左括号,则要进行右括号匹配,并判断中间是不是表达式,并得出表达式的值进行返回
        else if(results[sym].first == "lparen"){
            advance();
            arg = E2();
            if(results[sym].first == "rparen"){
                advance();
            }
            else{
                cout << "未能匹配右括号!\n";
                exit(0);
               }
        }
        return arg;
    }
    int T2()/*项分析*/
    {
        string op;
        int arg1, arg2, result;
        arg1 = F2();
        while(results[sym].first == "times" || results[sym].first == "slash"){
            op = results[sym].second;
            advance();
            arg2 = F2();
            if(op == "*"){
                result = arg1 * arg2;
                arg1 = result;
            }
            else{
                if(arg2 != 0){
                    result = arg1 / arg2;
                    arg1 = result;
                }
                else {
                    cout << "除数不能为0!\n";
                    exit(0);
                }
            }
        }
        return arg1;//返回该项所代表的值
    }
    int E2()/*表达式分析*/
    {
        string op;
        int arg1, arg2, result;
        if(results[sym].first == "plus" || results[sym].first == "minus"){
            advance();
        }
        arg1 = T2();//通过项分析得到第一个参数的值
        while(results[sym].first == "plus" || results[sym].first == "minus"){
            op = results[sym].second;
            advance();
            arg2 = T2();//通过项分析得到第二个参数的值
            if(op == "+"){
                result = arg1 + arg2;
                arg1 = result;
            }
            else{
                result = arg1 - arg2;
                arg1 = result;
            }
        }
        return arg1;//返回该表达式所代表的值
    }
    int main()
    {
        Lexical_Analysis(); //词法分析
        if(results[0].first == "number"){ //算术表达式
            cout << E2();
        }
        else{
            E1();
            for(int i=0; i<quaI; i++){  //表达式        cout<<'('<<quad[i].op<<','<<quad[i].arg1<<','<<quad[i].arg2<<','<<quad[i].result<<')'<<endl;
            }
        }
        return 0;
    }
    

    2.程序运行结果截图
    测试数据一
    在这里插入图片描述
    测试数据二
    在这里插入图片描述

    展开全文
  • 表达式中间代码生成 二、实验目的 熟悉算术表达式的语法分析与中间代码生成原理。 三、实验内容 1. 构造算术表达式的四元式翻译文法 2. 设计算术表达式的递归下降子程序分析算法 3. 设计算术表达的四元式生成算法...
  • 本程序用C语言编写,在Visual studio 6.0 下运行成功 拷贝之后便可以运行。 本程序是本人在学习编译...由于只是为了实验课的需要而用,所以程序的功能还十分简单,程序中也还存在很多问题和不足,欢迎大家给予指正。
  • 标准文档 语义分析及中间代码生成程序设计原理与实现技术 XXX 1028XXX2 计科1XXX班 1. 程序功能描述 完成以下描述赋值语句和算术表达式文法的语法制导生成中间代码四元式的过程 G[A]:AV:=E EE+TE-T TT*FT/FF F(E)i ...
  • 编译方法实验报告(中间代码生成器).pdf
  • 编译方法实验报告(中间代码生成器的设计).pdf
  • 编译原理实验:语义分析及中间代码生成

    万次阅读 多人点赞 2018-09-29 22:47:27
    实验题目:语义分析及中间代码生成实验目的实验内容实验要求输入输出2. 设计思想3.算法流程4. 源程序5. 调试数据 1. 实验题目:语义分析及中间代码生成 实验目的 通过上机实习,加深对语法制导翻译原理的理解,...
  • 包括词法分析器、lr(k)语法分析器、递归下降语法分析器、中间代码生成器以及对应的实验报告中间代码生成器是在词法分析器和语法分析器的基础上做的。写的很乱仅供参考。
  • 1. 构造算术表达式的四元式翻译文法 2. 设计算术表达式的递归下降子程序分析算法 3. 设计算术表达的四元式生成算法 4. 实现代码并调试运行

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,575
精华内容 5,030
热门标签
关键字:

中间代码生成实验报告