0

私はコンパイラを書いていて、無限にネストされたifステートメントを処理するための作業コードを持っていますが、それはハックのようなものです. これを行うのが安全かどうかわかりませんか?

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 / elseに対して同じアクションを使用できるようになり、文法の競合を回避できます。これは、解析している時点では、IF..DO存在するかどうかがわからないELSEためです。

于 2012-10-24T23:42:22.457 に答える