第八章语法制导翻译和中间代码生成8.1语法制导翻译语法制导翻译:在产生式中加入相应的语义动作,并在语法分析的同时执行这些语义动作。扩充CFG语法符号属性——语法树节点,记录域产生式语义规则——语法树节点,用于计算属性属性类型综合,synthesized,根据孩子节点属性计算继承,inherited,由父、兄弟节点属性计算8.1语法制导定义的形式每个产生式A与一组语义规则相关联,每个语义规则具有如下形式:b=f(c1,c2,…,ck),两种可能情况b为A的综合属性,c1,c2,…,ck为A、中语法符号的属性b为中某个符号的继承属性,c1,c2,…,ck为A、中语法符号的属性b依赖c1,c2,…,ck例8.1digit.lexval:终结符只有综合属性,由词法分析器提供开始符号通常没有继承属性LEnprint(E.val)EE1+TE.val=E1.val+T.valETE.val=T.valTT1*FT.val=T1.val*F.valTFT.val=F.valF(E)F.val=E.valFdigitF.val=digit.lexval产生式语义规则8.2自底向上计算S-属性定义与LR(1)分析器结合在栈中保存语法符号的属性值归约时,利用栈中语法符号(产生式右部)属性值计算新的(左部符号的)综合属性值自底向上计算S-属性定义示例AXYZA.a=f(X.x,Y.y,Z.z)val[ntop]=f(val[top-2],val[top-1],val[top])例8.2LEnprint(val[top])EE1+Tval[ntop]=val[top-2]+val[top]ETTT1*Fval[ntop]=val[top-2]*val[top]TFF(E)val[ntop]=val[top-1]Fdigit产生式代码片断8.2中间代码一、逆波兰表示法:后缀式1、把运算量写在前面,算符写在后面,不用括号的表示法。a*(b+c)=>abc+*(a+b)*(c+d)=>ab+cd+*2、计值方法:适合栈来计算:从左到右扫描后缀式,碰到运算量就推进栈;碰到K目运算就作用于栈顶的K项,并将运算结果代替这K项。abcab+ca*(b+c)3、后缀式的推广推广到比表达式更大的范围例:ifethenxelsey可表示成exy#,#代表三目运算符if-then-else.二、三元式(op,arg1,arg2)A+B*C:OPARG1ARG2(1)*BC(2)+A(1)间接三元式用一张间接码表辅以三元式表,表示中间代码。例:X:=(A+B)*CY:=D^(A+B)间接码表三元式表(1)oparg1arg2(2)(1)+AB(3)(2)*(1)C(1)(3):=x(2)(4)(4)^D(1)(5)(5):=Y(4)间接三元式优点:便于优化时调整运算顺序,只需重新安排码表,无需改动三元式表。相同的三元式无需重复填进三元式表中,节省空间。三、四元式(OP,ARG1,ARG2,RESULT)...