2012-10-24 43 views
0

我正在编写一个编译器,并且我有用于处理无限嵌套if语句的工作代码,但它有点破解。我不知道这样做是否安全?这是对Bison的安全编程吗?

con_statement: 
IF exp DO 
{ 
    $1 = ifNum++; 
    if($2 == BOOLEAN_TYPE || $2 == INTEGER_TYPE) 
    { 
     utstring_printf(code, "\tpop\teax\n"); 
     utstring_printf(code, "\tcmp\teax, 0\n"); 
     utstring_printf(code, "\tje\tIF_END_%d\n", $1); 
    } 
    if($2 == FLOAT_TYPE) 
    { 
     utstring_printf(code, "\tnop\n"); 
    } 
} 
program FI 
{ 
    utstring_printf(code, "IF_END_%d:\n", $1); 
} 
; 
+0

你在担心什么?标签生成?代码生成?规则的“程序”部分?目前还不清楚你如何处理ELSE条款......也许这并不重要,但它通常是这样。 –

+0

说$ 1 = LABELNUM并输入终端对我来说似乎是一个糟糕的混乱?对不起,我忘了完成输入, – SetSlapShot

+1

由于默认操作是设置'$$ = $ 1;',使用'$ 1'这样的默认操作可能会产生分支上游,但它不应该影响Yacc代码 - 只是您的任何操作看着'con_statement'返回的值。我认为创建一种机制将标签号与当前结构关联起来更为传统。我认为你在做的是非常规的。它认为它可能会在以后对你产生影响。但我认为它不会打破Yacc本身。 –

回答

1

这工作得很好,但是这将是国际海事组织更清晰的使用$$/$ 4:

con_statement: 
IF exp DO 
{ 
    $$ = ifNum++; 
    if($2 == BOOLEAN_TYPE || $2 == INTEGER_TYPE) 
    { 
     utstring_printf(code, "\tpop\teax\n"); 
     utstring_printf(code, "\tcmp\teax, 0\n"); 
     utstring_printf(code, "\tje\tIF_END_%d\n", $$); 
    } 
    if($2 == FLOAT_TYPE) 
    { 
     utstring_printf(code, "\tnop\n"); 
    } 
} 
program FI 
{ 
    utstring_printf(code, "IF_END_%d:\n", $4); 
} 
; 

第一个动作是生成一个值(它付诸$$),再到后来的行动能访问该值。

交替(特别是如果你想支持ELSE),它可能是有意义的这一初步行动分离到单独的生产:

con_statement: 
    if_head program FI 
    { utstring_printf(code, "IF_FALSE_%d:\n", $1); } 
| if_head program ELSE 
    { utstring_printf(code, "\tjmp\tIF_END_%d\n", $1); 
     utstring_printf(code, "IF_FALSE_%d:\n", $1); } 
    program FI 
    { utstring_printf(code, "IF_END_%d:\n", $1); } 
; 

if_head: 
    IF exp DO 
    { $$ = ifNum++; 
      : 
; 

这允许使用相同的操作对普通if和if/else语句,避免语法冲突,因为在解析IF..DO时您不知道是否会有ELSE