编译原理|第7章|布尔表达式的翻译

  1. 数值表示法
    1. 如同计算算数表达式一样,一步步计算(先算括号,后外面)
    2. 例子:
      1. a or b and not c 翻译成:

                          T1=not c

                          T2=b and T1

                          T3=a and T2

                     2.   a

                         if a

                         翻译成:

                               100:if a

                               101: T=0

                              102: goto 104

                               103: T=1

                               104:

  • 关于布尔表达式的数值表示法的翻译模式
    • 过程emit将三地址代码输送到文件中
    • nextstat:输出下一条三地址语句的地址索引
    • 过程emit每产生一条指令,nextstat加1
    • E->E1 or E2 {
      • E.place:=newtemp
      • emit( E.place:=E1.place or E2.place)}
        • E.place是E.code存储的三地址代码的位置,或者变量
    • E->E1 and E2 {
      • E.place=newtemp
      • emit(E.place=E1.place and E2.place)}
    • E->not E1 {
      • E.place:newtemp
      • emit(E.place=not E1.place)}
    • E->(E1){
      • E.place=E1.place}
    • E->id1 relop id2 {
      • E.place=newtemp,
      • emit(if id1 relop id2 goto nextstat+3),
      • emit(E.place=0)
      • emit(goto nextstat+2)
      • emit(E.place=1)}
    • E->id {E.place=id.place}
  • 例子:布尔表达式a
  • 100:if a
  • 101: T1=0
  • 102: goto 104
  • 103: T1=1
  • 104: if c
  • 105: T2=0
  • 106: goto 108
  • 107: T2=1
  • 108: if e
  • 109: T3=0
  • 110: goto 112
  • 111: T3=1
  • 112: T4=T3 and T2
  • 113: T5=T4 or T1
  • 产生布尔表达式三地址代码的属性文法(语法规则)
    • newlabel产生一个新的符号标号
    • 对于一个布尔表达式E,设置两个属性
      • E.true是E为真的时候的控制流向的标号
      • E.false是E为假的时候的控制流向的标号
      • E.code记录E生成的三地址代码的序列
      • E->E1 or E2
          • E1.true =E.true
          • E1.false=newlabel
          • E2.true=E.true
          • E2.false=E.false
          • E.code=E1.code||gent(E1.false)E2.code
      • E->E1 and E2
          • E1.true =newlabel
          • E1.false=E.false
          • E2.true=E.true
          • E2.false=E.false
          • E.code=E1.code||gen(E1.true)||E2.code
      • E->not E1
          • E.true=E1.false
          • E.false=E1.true
          • E.code=E1.code
      • E->(E1)
          • E.true=E1.true
          • E.false=E1.false
          • E.code=E1.code
      • E->id1 relop id2
          • E.code=gen(if id1.place relop id2.place goto E.true )||gen(goto E.false)
      • E->true
          • E.code=gen(goto true)
      • E->false
          • E.code=gen(goto false)
  • 根据属性文法翻译布尔表达式:a
  • 具体过程不详细说明,大概过程就是根据属性文法(语法规则),先画出语法树,然后再自上而下分析每一个表达式的真假出口,然后再自下而上写出代码
  • 然而刚才的翻译是2遍扫描,提出了优化的翻译方法:自下而上一次扫描并翻译
  • 一遍扫描实现布尔表达式 的翻译
    • 以四元式为中间语言
    • 四元式存入一个数组中数组下标代表四元式的标号
    • 约定:
      • 四元式(jnz,a,-,p):代表 if a goto p
      • 四元式 (jrop x,y,p):代表 if x rop y goto p
      • 四元式 (j,-,-p) :goto p
      • 过程emit将四元式代码送到输出数组中
      • 产生四元式时,他的转移地址无法立刻知道,需要以后扫描到特定位置时才能回过头来确定,保存,等待回填
      • 为非终结符E赋予两个综合属性,E.truelist和E.falselist,分别记录布尔表达式,E所对应的四元式中需要回填真,和假的出口的四元式的标号所构成的链表
    • 引入语义变量和过程
      • nextquad 指向下一条将要产生的但是没有产生的四元式的地址,初值为1,每当执行一次emit,就自增1
      • makelist(i),创建一个只有i的新链表,其中i是四元式数组的一个下标,返回指向这个链表的指针(开始的时候才用)
      • merge(p1,p2),把p1和p2为链首的两条链合并成一条,返回合并后的链首
      • backpatch(p,t),回填,把p所链接的每个四元式的第四区填成t
    • 布尔表达式的翻译模式
      • M->e
        • M.quad=nextquad
      • E->E1 or M E2
        • backpatch(E1,M.quad)
        • E.truelist=Merge(E1.truelist,E2.truelist)
        • E.falselist=E2.falselist
      • E->E1 and M E2
        • backpatch(E1,truelist,M.quad)
        • E.truelist=E2.truelist
        • E.falselist=Merge(E1,falselist,E2.falselist)
      • E->not E1
        • E.truelist=E1.falselist
        • E.falselist=E1.truellist
      • E->(E1)
        • E.truelist=E1.truelist
        • E.falselist=E1.falselist
      • E->id1 relop id2
        • E.truelist=makelist(nextquad);
        • E.falselist=makelist(nextquad+1);
        • emit(j relop id1.place id2.place,0);
        • emit(j,-,-0);
      • E->id
        • E.truelist=makelist(nextquad)
        • E.falselist=makelist(nextquad+1);
        • emit(j relop, id.place,-0)
        • emit(j,-,-0);
  •  

    你可能感兴趣的:(编译原理|第7章|布尔表达式的翻译)