SetSlapShot
SetSlapShot

Reputation: 1298

Is this safe programming for Bison?

I'm writing a compiler, and I have working code for handling infinitely nested if statements, but it's kind of a hack. I don't know if it's safe to do this?

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

Upvotes: 0

Views: 87

Answers (1)

Chris Dodd
Chris Dodd

Reputation: 126378

This works fine but it would be IMO clearer to use $$/$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);
}
;

The first action is generating a value (which it puts into $$), and then later actions can access that value.

Alternately (and particularly if you want to support ELSE), it may make sense to split this initial action onto a separate production:

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++;
          :
;

This allows using the same action for plain if and if/else, avoiding a grammar conflict, since at the point you are parsing the IF..DO you don't know whether there will be an ELSE or not.

Upvotes: 1

Related Questions