0

I'm new to bison.. I've wrote a grammar rule for if, else if and else statement.. I got reduce reduce conflict though.. Can anyone help ? I've tried everything I've found but as I told I'm new and I don't understand exactly what happens..

Here's my code:

ifinstr: KW_IF expr_decl KW_THEN statements elseifinstr elseinstr KW_END  
;
elseifinstr : %empty {$$ = "";}
            | elseifinstr KW_ELSE KW_IF expr_decl KW_THEN statement 
;
elseinstr : %empty {$$ = "";}
          | KW_ELSE statement
;

I've tried this solution too but got shift/reduce conflict instead:

ifinstr: KW_IF expr_decl KW_THEN statements elseifinstr KW_END  
;
elseifinstr : %empty {$$ = "";}
            | elseifinstr KW_ELSE KW_IF expr_decl KW_THEN statement 
            | KW_ELSE statement 
;

1 Answers1

0

The problem is that the grammar you propose is ambiguous. (The first grammar, I mean. The proposed second solution is a different language.)

Languages which use an "else if" construct in order to cut down on the nesting of "if … end" brackets use a special token:

Ruby               Python                VB                  Shell
----------------   -------------------   -----------------   --------------------
if n > 0           if n > 0:             If n > 0 Then       if ((n>0)); then
  puts "Greater"     print ("Greater")     Print "Greater"     echo Greater
elsif n == 0       elif n == 0:          ElseIf n = 0 Then   elif ((n==0)); then
  puts "Equal"       print ("Equal")       Print "Equal"       echo Equal
else               else:                 Else                else
  puts "Less"        print ("Less")        Print "Less"        echo Less
end                                      End                 fi

Without the fused "else if", these expressions would be much more cumbersome:

Ruby               Python                VB                  Shell
----------------   -------------------   -----------------   --------------------
if n > 0           if n > 0:             If n > 0 Then       if ((n>0)); then
  puts "Greater"     print ("Greater")     Print "Greater"     echo Greater
else               else:                 Else                else 
  if n == 0          if n == 0:            If n = 0 Then       if ((n==0)); then
    puts "Equal"       print ("Equal")       Print "Equal"       echo Equal
  else               else:                 Else                else
    puts "Less"        print ("Less")        Print "Less"        echo Less
  end                end                   End                 fi
end                                      End                 fi

This constrasts with languages like C, Java, and many others which do not require that "if" statements be terminated, and thus exhibit the "dangling else" shift-reduce conflict, which is always resolved in favour of the shift. In those languages, since the "else" clause simply attaches to the closest unmatched "if" clause, there is no need to provide a special "else-if" token.

Now, you are attempting to combine these two approaches by using a fused "else-if" without fusing it, and that simply leads to the same dangling else problem which the explicit bracketing was attempting to fix. Consider, for example:

 if C1 then S1 else if C2 then S2 else if C3 then S3 else S4 end S5 end

Now, which of the following two does this represent?

 if C1 then                       if C1 then
   S1                               S1
 else if C2 then                  else
   S2                               if C2 then
 else                                 S2
   if C3 then                       else if C3 then
     S3                               S3
   else                             else
     S4                               S4
   end                              end
   S5                               S5
 end                              end   

(With more time I might have found a simpler example. The above two interpretations differ in the circumstances in which S5 is executed.)

The simplest solution is to use some fused "else if" token, as in the various language examples above. (Or think up your own :-) )

rici
  • 234,347
  • 28
  • 237
  • 341