0

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

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);
}
;
4

1 回答 1

1

这很好用,但使用 $$/$4 会更清楚 IMO:

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您不知道是否会有 an ELSE

于 2012-10-24T23:42:22.457 回答