Bison Difficult Dangling Else Removal

75 Views Asked by At

I am trying to get rid of dangling else in my grammar. Terminals are capital-letter words. I have:

statement:
    expression_statement (not important now )
    | compound_statement (not important now )
    | selection_statement
    | iteration_statement (not important now but maybe yes ? it contains statement non-terminal )
    | jump_statement (not important now )
    ;

selection_statement:
    IF LPAR expression RPAR statement
    | IF LPAR expression RPAR statement ELSE statement
    ;

iteration_statement:
    WHILE LPAR expression RPAR statement
    | DO statement WHILE LPAR expression RPAR SEMIC
    | FOR LPAR expression_opt SEMIC expression_opt SEMIC expression_opt RPAR statement
    ;

I tried this approach

statement:
    expression_statement
    | compound_statement
    | selection_statement_o
    | selection_statement_c
    | iteration_statement
    | jump_statement
    ;

selection_statement_o:
    IF LPAR expression RPAR statement
    | IF LPAR expression RPAR selection_statement_c ELSE selection_statement_o
    ;

selection_statement_c:
    IF LPAR expression RPAR selection_statement_c ELSE selection_statement_c
    ;

I am stuck now and don't know what to do. How should I correctly remove dangling else here ? Thanks for any help.

EDIT 1: I tried this approach and I got less shift/reduce conflicts and more reduce/reduce conflicts I guess it is not right :D but here it is

statement:
    matched
    | unmatched
    | other
    ;

other:
    expression_statement
    | compound_statement
    | jump_statement
    ;

matched:
    selection_statement_c
    | iteration_statement_c
    ;

unmatched:
    selection_statement_o
    | iteration_statement_o
    ;

selection_statement_o:
    IF LPAR expression RPAR statement
    | IF LPAR expression RPAR matched ELSE unmatched
    ;

selection_statement_c:
    IF LPAR expression RPAR matched ELSE matched
    ;

iteration_statement_o:
    WHILE LPAR expression RPAR unmatched
    | DO statement WHILE LPAR expression RPAR SEMIC
    | FOR LPAR expression_opt SEMIC expression_opt SEMIC expression_opt RPAR unmatched
    ;

iteration_statement_c:
    WHILE LPAR expression RPAR matched
    | DO statement WHILE LPAR expression RPAR SEMIC
    | FOR LPAR expression_opt SEMIC expression_opt SEMIC expression_opt RPAR matched
    ;

0

There are 0 best solutions below