0

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
    ;

Riomare
  • 65
  • 1
  • 10
  • You've refactor the wrong place(s) -- you need to refactor the statement *before* the ELSE to disallow dangling else. – Chris Dodd Nov 11 '21 at 18:05
  • Im sorry but I really can't see how it should be done @ChrisDodd – Riomare Nov 11 '21 at 19:32
  • 1
    You've almost got it -- just remove the redundant `DO` rule from `iteration_statement_o` and you're done. `DO` can't end with an unmatched if, so should only be in the _c rule not the _o rule. – Chris Dodd Nov 11 '21 at 22:00
  • 1
    @riomare: [Wikipedia article, with example grammars](https://en.wikipedia.org/wiki/Dangling_else#Avoiding_the_conflict_in_LR_parsers). Alternatively, [an answer here on SO](https://stackoverflow.com/questions/34254103/shift-reduce-conflict-in-java-cup-dangling-else-issue/34256059#34256059) – rici Nov 11 '21 at 22:01

0 Answers0