I’m having a problem understanding the shift/reduce confict for a grammar that I know has no ambiguity. The case is one of the if else type but it’s not the ‘dangling else’ problem since I have mandatory END clauses delimiting code blocks.
Here is the grammar for gppg (Its a Bison like compiler compiler … and that was not an echo):
%output=program.cs %start program %token FOR %token END %token THINGS %token WHILE %token SET %token IF %token ELSEIF %token ELSE %% program : statements ; statements : /*empty */ | statements stmt ; stmt : flow | THINGS ; flow : '#' IF '(' ')' statements else ; else : '#' END | '#' ELSE statements '#' END | elseifs ; elseifs : elseifs '#' ELSEIF statements else | '#' ELSEIF statements else ;
Here is the conflict output:
// Parser Conflict Information for grammar file 'program.y' Shift/Reduce conflict on symbol ''#'', parser will shift Reduce 10: else -> elseifs Shift ''#'': State-22 -> State-23 Items for From-state State 22 10 else: elseifs . -lookahead: '#', THINGS, EOF 11 elseifs: elseifs . '#' ELSEIF statements else Items for Next-state State 23 11 elseifs: elseifs '#' . ELSEIF statements else // End conflict information for parser
I already switched arround everything, and I do know how to resolve it, but that solution involves giving up the left recursion on ‘elseif’ for a right recursion.
Ive been through all the scarse documentation I have found on the internet regarding this issue (I post some links at the end) and still have not found an elegant solution. I know about ANTLR and I don’t want to consider it right now. Please limit your solution to Yacc/Bison parsers.
I would appreciate elegant solutions, I managed to do It by eleminating the /* empty */ rules and duplication everything that needed an empty list but in the larger grammar Im working on It just ends up like ‘sparghetti grammar syndrome’.
Here are some links:
http://nitsan.org/~maratb/cs164/bison.html
Your revised ELSEIF rule has no markers for a condition — it should nominally have ‘(‘ and ‘)’ added.
More seriously, you now have a rule for
and
The ‘nothing’ is not needed; it is implicitly taken care of by the ‘elsebody’ without the ‘elseifs’.
I would be very inclined to use rules ‘opt_elseifs’, ‘opt_else’, and ‘end’:
I’ve not run this through a parser generator, but I find this relatively easy to understand.