- 数值表示法
- 如同计算算数表达式一样,一步步计算(先算括号,后外面)
- 例子:
- a or b and not c 翻译成:
T1=not c
T2=b and T1
T3=a and T2
2. a<b的关系表达式可以等价地写成
if a<b then 1 else 0
翻译成:
100:if a<b goto103
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<b or c<d and e<f 的翻译结果
- 100:if a<b goto 103
- 101: T1=0
- 102: goto 104
- 103: T1=1
- 104: if c<d goto 107
- 105: T2=0
- 106: goto 108
- 107: T2=1
- 108: if e<f goto 111
- 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<b or c<d and e<f 假设整个表达式的真假出口设置为Ltrue和Lfalse
- 具体过程不详细说明,大概过程就是根据属性文法(语法规则),先画出语法树,然后再自上而下分析每一个表达式的真假出口,然后再自下而上写出代码
- 然而刚才的翻译是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);
- M->e