s1
in an if-then-else form:
if a then if b then s else s2
In this example, s
is unambiguously executed when a
is true and b
is true, but one may interpret s2
as being executed when a
is false (thus attaching the else to the first if) or when a
is true and b
is false (thus attaching the else to the second if). In other words, one may see the previous statement as either of the following expressions:
if a then (if b then s) else s2
if a then (if b then s else s2)
The dangling else problem dates to Avoiding ambiguity while keeping the syntax
This is a problem that often comes up in compiler construction, especially scannerless parsing. The convention when dealing with the dangling else is to attach the else to the nearby if statement, allowing for unambiguous context-free grammars, in particular. Programming languages like Pascal, C and Java follow this convention, so there is no ambiguity in the semantics of the ''language'', though the use of a parser generator may lead to ambiguous ''grammars''. In these cases alternative grouping is accomplished by explicit blocks, such asbegin...end
in Pascal and
in C.
Depending on the compiler construction approach, one may take different corrective actions to avoid ambiguity:
*If the parser is produced by an SLR, LR(1) or LALR LR parser generator, the programmer will often rely on the generated parser feature of preferring shift over reduce whenever there is a conflict. Alternatively, the grammar can be rewritten to remove the conflict, at the expense of an increase in grammar size (see Avoiding ambiguity by changing the syntax
The problem can also be solved by making explicit the link between an else and its if, within the syntax. This usually helps avoid human errors. Possible solutions are: *Having an "end if" symbol delimiting the end of the if construct. Examples of such languages are ALGOL 68, Ada, Eiffel, PL/SQL, Visual Basic,if
without a fallback clause to be an error, effectively distinguishing conditional ''expressions'' (i.e if
) from conditional ''statements'' (i.e when
and unless
, which do not have fallback clauses).
*Using different keywords for the one-alternative and two-alternative "if" statements. S-algol uses if e do s
for the one-alternative case and if e1 then e2 else e3
for the general case.
* Requiring braces unconditionally, like Swift. This is effectively true in Python as its indentation rules delimit every block, not just those in "if" statements.
Examples
Concrete examples follow.C
In C, the grammar reads, in part:statement = ... , selection-statement selection-statement = ... , IF ( expression ) statement , IF ( expression ) statement ELSE statementThus, without further rules, the statement
else
with the nearest if
.
Avoiding the conflict in LR parsers
The above example could be rewritten in the following way to remove the ambiguity :statement: open_statement , closed_statement ; open_statement: IF '(' expression ')' statement , IF '(' expression ')' closed_statement ELSE open_statement ; closed_statement: non_if_statement , IF '(' expression ')' closed_statement ELSE closed_statement ; non_if_statement: ... ;Any other statement-related grammar rules may also have to be duplicated in this way if they may directly or indirectly end with a
statement
or selection-statement
non-terminal.
However, we give grammar that includes both of if and while statements.
statement: open_statement , closed_statement ; open_statement: IF '(' expression ')' statement , IF '(' expression ')' closed_statement ELSE open_statement , WHILE '(' expression ')' open_statement ; closed_statement: simple_statement , IF '(' expression ')' closed_statement ELSE closed_statement , WHILE '(' expression ')' closed_statement ; simple_statement: ... ;Finally, we give the grammar that forbids ambiguous IF statements.
statement: open_statement , closed_statement ; open_statement: IF '(' expression ')' simple_statement , IF '(' expression ')' open_statement , IF '(' expression ')' closed_statement ELSE open_statement , WHILE '(' expression ')' open_statement ; closed_statement: simple_statement , IF '(' expression ')' closed_statement ELSE closed_statement , WHILE '(' expression ')' closed_statement ; simple_statement: ... ;With this grammar parsing of "if (a) if (b) c else d" fails:
statement open_statement IF '(' expression ')' closed_statement ELSE open_statement 'if' '(' 'a' ')' closed_statement 'else' 'd'and then the parsing fails trying to match
closed_statement
to "if (b) c". An attempt with closed_statement
fails in the same way.
See also
* The lexer hack * Most vexing parseReferences
{{DEFAULTSORT:Dangling Else Parsing Computer programming Ambiguity Conditional constructs