I am getting the following error:
Warning : *** Shift/Reduce conflict found in state #116
between Statement ::= Matched (*)
and Unmatched ::= IF LPAREN Condition RPAREN Matched (*) ELSE Unmatched
and Matched ::= IF LPAREN Condition RPAREN Matched (*) ELSE Matched
under symbol ELSE
Resolved in favor of shifting.
Now, i am aware of the dangling else problem, and i have tried making the grammar unambiguous:
Statement ::= Matched | Unmatched ;
Matched ::= IF LPAREN Condition RPAREN Matched ELSE Matched
|
Others
;
Unmatched ::= IF LPAREN Condition RPAREN Statement
|
IF LPAREN Condition RPAREN Matched ELSE Unmatched
;
Is there any way to resolve this problem without the precedence operator, or is there something else wrong with the grammar?
There is nothing wrong with the grammar presented in the question, so my guess is that the shift/reduce conflict is the result of an interaction with another production.
The idea of splitting statements into
Matched
andUnmatched
:is precisely to ensure that an else is correctly matched with the nearest unmatched if. A
Matched
statement cannot be extended with an else clause; anUnmatched
statement could have been. So we require that else tokens in the grammar cannot followUnmatched
statements, thus avoiding prematurely reducing a statement which might have been extended with anelse
clause.So inside the
If
statement, the else can only follow aMatched
statement. The statement itself isUnmatched
if it doesn't have anelse
clause, or if theelse
clause itself isUnmatched
. Thus, we have three productions:But this isn't the whole story, because there are other possible compound statements. Consider, for example, a
while
statement. If the language has such a construct, the grammar probably includes something like this:That won't work, because a
while
statement can also beUnmatched
, in precisely the same way that anif...else
statement can be: if the interiorStatement
isUnmatched
.For example, consider
With the incorrect
While
production above, that would be reduced as follows:But that violates the requirement that
Unmatched
cannot be followed by else.Matched
can be followed by else, but in this case theMatched
ends withUnmatched_If
. And consequently, we have a shift/reduce conflict:This could be parsed as
But that is not actually the intended parse. (The indentation might lead us to think that it was the programmer's intent, but it is not the intent of the language designer.) The else should match the second if, not the first one, leading to:
So we need to distinguish between matched and unmatched
While
statements, not just matched and unmatchedIf
statements:With that,
while (x) if (y) do_x_and_y;
will be parsed as anUnmatched_While
, and so it can no longer be part of the productions which startIF LPAREN Condition RPAREN Matched ELSE...
Of course, the same will need to be done for other compound statements, such as
for
statements.So the final result will be something like: