additive-expressionR --> ADDOP term {additive-expressionR.n := newtemp} {Par_table_chain.enter(additive-expressionR.n, \ {Quads_code.gen_tri(Par_table_chain, ADDOP.name,
additive-expressionR.n, additive-expressionR.i, term.name)} {additive-expressionR1.i := additive-expressionR.n} additive-expressionR1
{additive-expressionR.s := additive-expressionR1.s}
additive-expressionR --> empty {additive-expressionR.s := additive-expressionR.i}
上面的文法是经过了消除左递归的(语法制导翻译中消除左递归的算法参见参考文献[1])。newtemp在当前作用域中返回一个临时变量的名字,第一次调用返回$1,第二次调用返回$2,以此类推。然后把这个临时变量放进符号表中。再生成以临时变量为result,以匹配到的标识符为arg1和arg2,(先在符号表中找到它,当前作用域的符号表找不到,则顺着符号表栈往上找,如果找到最外层符号表依然找不到,说明发生了未声明变量的调用,程序出错),以ADDOP的真值(+或-)为op的四元式,放进Quads_code结构中。
II. term --> factor {termR.i := factor.name} termR {term.name := termR.s} termR --> MULOP factor
{termR.n := newtemp} {Par_table_chain.enter(termR.n, \ {Quads_code.gen_tri(Par_table_chain, MULOP.name, termR.n, termR.i, factor.name)} {termR1.i := termR.n}
termR1 {termR.s := termR1.s} termR --> empty {termR.s := termR.i}
文法II实现的功能与I无异, II和I结合,能够实现算术表达式的左结合性和优先级规则。
III.factor --> (additive-expression) { factor.name := additive-expression.name} | ID {factor.name := ID.name} | call {factor.name := call.name}
| NUM { factor.name := int_to_str(NUM.value) } 操作符运算对象或者是变量,或者是函数调用返回的结果,或者是整型字面值,或者是括号中的表达式求得的值。
[4]控制流语句的翻译
I. selection-stmt --> \{ to_true := newlabel; to_false := newlabel } {condition-expression.to_true := to_true} {condition-expression.to_false := to_false}
condition-expression) {Quads_code.gen_label(to_true)}
statement {Quads_code.gen_label(to_false)} | \ { to_true := newlabel; to_false := newlabel } {condition-expression.to_true := to_true} {condition-expression.to_false := to_false}
condition-expression) {Quads_code.gen_label(to_true)} statement1 {to_next = newlabel}
“else”{Quads_code.gen_goto(to_next)}
{Quads_code.gen_label(to_false)}
statement2 {Quads_code.gen_label(to_next)}
FineC中的控制流语句有if-else和while两种。以上文法是if-else的翻译模式。if-then,if-then-else生成的三地址码如下图所示
to E.true E.code E.true S1.code E.false …… …… …… S.next …… …… …… to E.false E.code E.true S1.code goto S.next E.false S2.code to E.true to E.false
图3 if-then, if-then-else的中间代码
当匹配到\后,调用newlabel返回一个语句编号(第一次调用返回101,第二次102,第三次103,一次类推),to_true, to_false作为condition-expression的两个继承属性,用于生成E.code中条件转向三地址码的goto目的地。condition-expresson成功匹配后,生成一个三地址码“L101”,表示当上面的条件为真时,转向这一条语句往下执行,然后调用statement函数匹配if-then的执行函数体。匹配结束后,生成一个三地址码“L102”,表示当上面的条件为假是,转向这一条语句往下执行。这样一来,当condition-expression为假时,就自然地跨过了statement的语句不执行。
if-then-else的翻译与if-then有一样的原理,区别只在于E.false的指向是另一个statement,而在Statement1后面放一个无条件跳转语句,即表示“执行完statement1后不需要再执行statement2”。
II. iteration-stmt --> \{to_begin := newlabel} {Quads_code.gen_label(to_begin)} { to_true := newlabel; to_false := newlabel } {condition-expression.to_true := to_true} {condition-expression.to_false := to_false}
condition-expression) {Quads_code.gen_label(to_true)} statement {Quads_code.gen_goto(to_begin)} {Quads_code.gen_label(to_false)}
while语句生成的三地址码如下图所示
S.begin E.code E.true S1.code goto S.begin E.false …… …… …… to E.true to E.false
图4 while语句的中间代码
while语句的翻译思路也与if-then类似,只是在S1.code后面有一条“goto S.begin”,表示函数体执行结束后回到S.begin再次检查E.code的真假,当E.code为假时,跨过“goto S.begin”,也就结束了整个while的执行。注意,if-then语句和while语句的函数体都是statement,也就是说,它们都有各自的作用域。
III. condition-expression --> additive-expression1 RELOP additive-expression2 { Quads_code.gen_condition(Par_table_chain, RELOP.name, additive-expression1.name, additive-expression2.name, condition-expression.to_true) } { Quads_code.gen_goto(condition-expression.to_false)} 文法III生成布尔表达式E.code的代码,需要与文法I,II的翻译思路相匹配。 [5]过程声明和调用的翻译
函数声明的翻译已经在前面说明,下面是FineC语言中过程调用语句的翻译
I. call --> ID ( {call.name := newtemp } { Par_table_chain.enter(call.name, \
{ Quads_code.gen_uni(\
args ) { Quads_code.gen_call(Par_table_chain, ID.name) }
| ID ( {call.name := newtemp } { Par_table_chain.enter(call.name, \ {Quads_code.gen_uni(\
) { Quads_code.gen_call(Par_table_chain, ID.name) } II. args --> additive-expression
{ Quads_code.gen_param_load(Par_table_chain,
\
, args
| additive-expression
{ Quads_code.gen_param_load(Par_table_chain, \ additive-expression.name) }
当发生函数调用时,先生成一个当前作用域下的临时变量,用来代表返回值。然后生成一个“begin_args”的三地址码,表示开始发送实参。然后进入文法II匹配实参,每次匹配
到一个,输出一个“param 实参”形式的三地址码。实参匹配完毕后,生成“call 函数名”语句,转向相应的“enter 函数名”。
四、 FineC语言中间代码生成的完整翻译模式
1. program --> { Par_table_chain.mktable() } declaration-list
2.declaration-list --> declaration declaration-list1 | declaration1 3.declaration --> var-declaration
| { Par_table_chain.mktable() } fun-declaration {Par_table_chain.jumpout()}
4. var-declaration --> “int”ID; { Par_table_chain.enter(ID.name, \ 5. fun-declaration --> type-specifier ID
{ Par_table_chain.set_name_type(ID.name, type-specifier.type) } {Par_table_chain.add_to_previous()} { Quads_code.gen_entry(ID.name) } (params) compound-stmt | type-specifier ID
{ Par_table_chain.set_name_type(ID.name, type-specifier.type) } { Par_table_chain.add_to_previous() } { Quads_code.gen_entry(ID.name) } () compound-stmt
6. type-specifier --> \{ type-specifier.type := \
| \{ type-specifier.type := \ 7. params --> param, params | param
8. param --> \{ Par_table_chain.enter(ID.name, \
{Quads_code.gen_param_load(Par_table_chain, \ 9. compound-stmt --> {local-declarations statement-list}
10. local-declarations --> var-declaration local-declarations | empty 11. statement-list --> statement statement-list | empty
12. statement --> expression-stmt | selection-stmt | iteration-stmt | return-stmt
| { Par_table_chain.mktable() } {Par_table_chain.add_to_previous()} compound-stmt { Par_table_chain.jumpout() }
13. expression-stmt --> expression; | ;
14. selection-stmt --> \{ to_true := newlabel; to_false := newlabel } {condition-expression.to_true := to_true} {condition-expression.to_false := to_false}
condition-expression) {Quads_code.gen_label(to_true)} statement {Quads_code.gen_label(to_false)} | \ { to_true := newlabel; to_false := newlabel } {condition-expression.to_true := to_true} {condition-expression.to_false := to_false}
condition-expression) {Quads_code.gen_label(to_true)} statement1 {to_next = newlabel}
“else”{Quads_code.gen_goto(to_next)} {Quads_code.gen_label(to_false)}
statement2 {Quads_code.gen_label(to_next)}
15. iteration-stmt --> \{to_begin := newlabel}
{Quads_code.gen_label(to_begin)} { to_true := newlabel; to_false := newlabel } {condition-expression.to_true := to_true} {condition-expression.to_false := to_false}
condition-expression) {Quads_code.gen_label(to_true)} statement {Quads_code.gen_goto(to_begin)} {Quads_code.gen_label(to_false)}
16. condition-expression --> additive-expression1 RELOP additive-expression2 { Quads_code.gen_condition(Par_table_chain, RELOP.name, additive-expression1.name, additive-expression2.name, condition-expression.to_true)}
{ Quads_code.gen_goto(condition-expression.to_false)} 17.return-stmt --> “return”; { Quads_code.gen_uni(\ | “return”expression;
{Quads_code.gen_param_load(Par_table_chain, \ expression.name)}
18.expression --> ID = expression1
{ Quads_code.gen_bi(Par_table_chain, ID.name,expression1.name)} { expression.name := ID.name } | additive-expression
{ expression.name :=additive-expression.name }
19. additive-expression --> term {additive-expressionR.i := term.name} additive-expressionR
{additive-expression.name := additive-expressionR.s} 20. additive-expressionR --> ADDOP term {additive-expressionR.n := newtemp} {Par_table_chain.enter(additive-expressionR.n, \ {Quads_code.gen_tri(Par_table_chain, ADDOP.name, additive-expressionR.n, additive-expressionR.i, term.name)} {additive-expressionR1.i := additive-expressionR.n} additive-expressionR1
{additive-expressionR.s := additive-expressionR1.s}
| empty {additive-expressionR.s := additive-expressionR.i} 21. term --> factor {termR.i := factor.name}
termR {term.name := termR.s}
22. termR --> MULOP factor {termR.n := newtemp}
{Par_table_chain.enter(termR.n, \ {Quads_code.gen_tri(Par_table_chain, MULOP.name, termR.n, termR.i, factor.name)} {termR1.i := termR.n}