How do I remove shift-reduce conflict for bison for the given grammar?
selection-stmt -> if ( expression ) statement |
if ( express
You need to recognize the fact that the middle statement
in the if-else case cannot be (or end with) a dangling if (an if with no else.) The easiest way to do that is to split the stmt
rule in two:
stmt -> stmt-ending-with-dangling-if | stmt-not-ending-with-dangling-if
stmt-not-ending-with-dangling-if ->
if ( expression ) stmt-not-ending-with-dangling-if else stmt-not-ending-with-dangling-if |
...other statements not ending with dangling if...
stmt-ending-with-dangling-if ->
if ( expression ) stmt |
if ( expression ) stmt-not-ending-with-dangling-if else stmt-ending-with-dangling-if |
...other statements ending with dangling if...
Any other stmt -> whatever
rule where whatever
doesn't end with a stmt
goes in the stmt-not-ending-with-if
rule, while any stmt
rule that DOES end in stmt
get split in two versions; an not-ending-with-if
version in the not-ending-with-if
rule and a dangling-if
version in the dangling-if
rule.
edit
A more complete grammar with other productions:
stmt : stmt-ending-with-dangling-if | stmt-not-ending-with-dangling-if
stmt-not-ending-with-dangling-if :
IF '(' expr ')' stmt-not-ending-with-dangling-if ELSE stmt-not-ending-with-dangling-if |
WHILE '(' expr ')' stmt-not-ending-with-dangling-if |
DO stmt WHILE '(' expr ')' ';' |
expr ';' |
'{' stmt-list '}'
stmt-ending-with-dangling-if:
IF '(' expr ')' stmt |
IF '(' expr ')' stmt-not-ending-with-dangling-if ELSE stmt-ending-with-dangling-if |
WHILE '(' expr ')' stmt-ending-with-dangling-if
Rules like WHILE (expr) stmt
get split in two (as they end with stmt
), while rules like expr;
do not.