I'm trying to write a small parser. Unfortunately I get a "shift-reduce conflict". Grammars are not my strong point, and I only need to get this one small thingy done. Here's the reduced grammar that produces the error:
stmts_opt -> stmts
;
stmts -> stmt
| stmts stmt
| stmsts
;
stmt -> id
| ITERATE content_stmt
| IF test then content_stmt ELSE content_stmt
| IF test then content_stmt
;
content_stmt: BEGIN stmt_opt END
| stmt
;
A solution giving the modified grammar would be highly appreciated.
Edit:
I modified my grammar suiting @rici's answer but the problem persists. Here is my actual grammar productions:
prog: BEGIN_PROG def_sprogram BEGIN_EXEC stmts_opt END_EXEC END_PROG
{ () }
;
def_sprogram: /* empty */ { () }
| define_new def_sprogram { () }
;
define_new: DEFINE_NEW_INSTRUCTION ID AS content_stmt SEMI { }
;
stmts_opt: /* empty */ { () }
| stmts { () }
;
stmts: stmt { () }
| stmts SEMI stmt { () }
| stmts SEMI { () }
;
content_stmt: BEGIN stmts_opt END { () }
| stmt { () }
;
stmt: open_stmt { () }
| closed_stmt { () }
;
open_stmt: ITERATE INT TIMES open_stmt { () }
| WHILE test DO open_stmt { () }
| IF test THEN closed_stmt ELSE open_stmt { () }
| IF test THEN stmt { () }
;
closed_stmt: simple_stmt { () }
| ITERATE INT TIMES closed_stmt { () }
| WHILE test DO closed_stmt { () }
| IF test THEN closed_stmt ELSE closed_stmt { () }
;
Here is the example I am testing on:
BEGINNING-OF-PROGRAM
BEGINNING-OF-EXECUTION
IF not-next-to-a-beeper THEN
move;
IF not-facing-north THEN
turnleft;
ELSE <--- ERROR
turnleft;
IF not-facing-east THEN
IF not-facing-west THEN
turnleft;
turnoff
END-OF-EXECUTION
END-OF-PROGRAM
I am getting the error in the first ELSE
. I also tried to declare a simple precedence as suggested by @rici:
%nonassoc THEN
%nonassoc ELSE
but that didn't resolve the error neither.