中间语言(简述)
▍后缀表达式
- 后缀表达式最大的优点是便于计算机处理(栈)
- 后缀表达式显著的特点是不需要括号
>>>【典例】
>>> 中缀表达式:-(x + y) * (y + z) - (x + y + z)
>>> 后缀表达式:xy+-yz+*xy+z+-
▍语法树
- 图形化的语法树更加直观
- 有向无环图(DAG)也是一种图形化的表示方法
- 构造语法树便于分析语法制导的语义计算
>>>【典例】
>>> a = (-b + c * d) + c * d(自己画画看,底下有答案)
▍三地址代码
- 三地址代码是「语法树」或「DAG」的一种线性表示
- 一般形式:
x = y op z
>>>【典例】
>>> x + y * z 翻译成三地址代码为:
>>> t1 = y * z
>>> t2 = x + t1
中间语言(图解)
中间代码生成(标号)
S -> if B then S1 else S2
//进入B前:
B.true = newLable();
B.false = newLable();
//进入S1前:
S1.next = S.next;
//进入S2前:
S2.next = S.next;
//访问S2后:
S.code = B.code || gen(B.true, ':') || S1.code || gen('goto', S.next) || gen(B.false, ':') || S2.code
S -> while B do S1
//访问while前:
S.begin = newLabel();
//访问B前:
B.true = newLabel();
B.false = S.next;
//进入S1前:
S1.next = S.begin;
//访问S1后:
S.code = gen(S.begin, ':') || B.code || gen(B.true, ':') || S1.code || gen('goto', S.begin)
中间代码生成(回填)
S -> if B then S1 else S2
//进入S1前:
instr1 = nextinstr;
//访问S1后:
nextlist = makeList(nextinstr);
emit('goto_')
//进入S2前:
instr2 = nextinstr;
//访问S2后:
backPatch(B.truelist, instr1);
backPatch(B.falselist, instr2);
S.nextlist = merge(merge(S1.nextlist, nextlist));
S -> while B do S1
//进入B前:
instr1 = nextinstr;
//进入S1前:
instr2 = nextinstr;
//访问S1后:
backPatch(S1.nextlist, instr1);
backPatch(B.truelist, instr2);
B.falselist = S.nextlist;
emit('goto', instr1);
中间代码生成(图解)
【标号】 if B then S1 else S2
【回填】 while(a > 0 and x < 0) {
x := x + 1;
if(a > 0 or b < 0) {
a := a + 1;
} else {
b := b - 1;
}
}
E N D END END