Backus-Naur Form specifications for the grammars of languages like like C or C++ build up expressions with counter-intuitive definitions. For instance, a multiplication expression like
5 * 3
is also a logical-or-expression
and an equality-expression
and a bunch of other things it doesn't actually look like, because the grammar makes it an:
expression
- consisting of an
assignment-expression
- consisting of a
conditional-expression
- consisting of a
logical-or-expression
- consisting of a
logical-and-expression
- consisting of an
inclusive-or-expression
- consisting of an
exclusive-or-expression
- consisting of an
and-expression
- consisting of an
equality-expression
- consisting of a
relational-expression
- consisting of a
shift-expression
- consisting of an
additive-expression
- consisting a
multiplicative-expression
.
- consisting a
- consisting of an
- consisting of a
- consisting of a
- consisting of an
- consisting of an
- consisting of an
- consisting of an
- consisting of a
- consisting of a
- consisting of a
- consisting of an
A snippet from the grammar looks like:
<exclusive-or-expression> ::= <and-expression>
| <exclusive-or-expression> ^ <and-expression>
<and-expression> ::= <equality-expression>
| <and-expression> & <equality-expression>
<equality-expression> ::= <relational-expression>
| <equality-expression> == <relational-expression>
| <equality-expression> != <relational-expression>
So if I were to write a parser that just followed these productions, I'd end up having to interpret the expression 5 * 3
12 different ways, e.g. by making it an instance of a MultiplicativeExpression class which derives from AdditiveExpression... all the way up to a base Expression class. And that seems very wasteful, since those classes would implement adding, AND-ing, OR-ing, etc. but would simply no-op for the single-term case.
By comparison, the Wikipedia example of BNF makes more sense:
<postal-address> ::= <name-part> <street-address> <zip-part>
<name-part> ::= <personal-part> <last-name> <opt-suffix-part> <EOL>
| <personal-part> <name-part>
<personal-part> ::= <initial> "." | <first-name>
...
The Wikipedia example reads like "a postal address consists of a [...]", whereas C-like language grammars read more like "a [...] can be treated as an expression". Why are C-like language grammars so "polymorphic"?