This problem 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,2 allowing for unambiguous context-free grammars, in particular. Programming languages like Pascal,3 C,4 and Java5 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 as begin...end in Pascal6 and {...} in C.
Depending on the compiler construction approach, one may take different corrective actions to avoid ambiguity:
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.8
Possible solutions are:
Concrete examples follow.
In C, the grammar reads, in part:
Thus, without further rules, the statement
could ambiguously be parsed as if it were either:
or:
The C standard clarifies that an else block is associated with the nearest if.12 Therefore, the first tree is chosen.
The above example could be rewritten in the following way to remove the ambiguity :
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.
Finally, we give the grammar that forbids ambiguous IF statements.
With this grammar the statement if (a) if (b) c else d can only be parsed one way, because the other interpretation (if (a) {if (b) c} else d) is produced as
and then the parsing fails trying to match closed_statement to "if (b) c". An attempt with closed_statement fails in the same way. The other parse, if (a) {if (b) c else d}) succeeds:
Abrahams, P. W. (1966). "A final solution to the Dangling else of ALGOL 60 and related languages". Communications of the ACM. 9 (9): 679–682. doi:10.1145/365813.365821. S2CID 6777841. https://doi.org/10.1145%2F365813.365821 ↩
"5.2 Shift/Reduce Conflicts". Bison 3.8.1. GNU. Retrieved 2021-08-07. https://www.gnu.org/software/bison/manual/html_node/Shift_002fReduce.html#Shift_002fReduce ↩
ISO 7185:1990 (Pascal) 6.8.3.4: An if-statement without an else-part shall not be immediately followed by the token else. ↩
ISO 9899:1999 (C): 6.8.4.1(3): "An else is associated with the lexically nearest preceding if that is allowed by the syntax.", available at WG14 N1256, p. 134 https://www.open-std.org/jtc1/sc22/wg14/www/standards ↩
"The Java Language Specification, Java SE 9 Edition, 14.5. Statements". https://docs.oracle.com/javase/specs/jls/se9/html/jls-14.html ↩
Dale, Nell B.; Weems, Chip (November 1996). "Dangling Else". Introduction to Pascal and Structured Design. Jones & Bartlett Learning. pp. 160–161. ISBN 9780763703974. 9780763703974 ↩
Ambiguity of dangling else: non-context-free grammars are semantically opaque https://code.google.com/archive/p/copute/issues/21#c2 ↩
4.5.1 Conditional Statements — Syntax in P. Nauer (ed.), Revised Report on the Algorithmic Language ALGOL 60, CACM 6,1, 1963 pp. 1-17 ↩
Ambiguity of dangling else: require braces when else follows if https://code.google.com/archive/p/copute/issues/21#c1 ↩
Davie, Antony J. T.; Ronald Morrison (1981), Brian Meek (ed.), Recursive Descent Compiling, Ellis Horwood series in computers and their applications, Chichester, West Sussex: Ellis Horwood, p. 20, ISBN 0-470-27270-8 0-470-27270-8 ↩