The issue, as I understand it, is that you need to know whether an identifier in certain contexts is a type name or not. C99 increases the number of contexts. Consider:
x * y;
If x is a type, this declares y as a pointer to elements of that type, if you're at the beginning of a block or in C99. If x is a variable, this is a multiplication in void context, unless you're at the top level of the translation unit. A somewhat more interesting example is
x *f();
which may declare f or call it, depending on what x is. Of course, lacking the ability to overload the multiplication operator, there's no reason you'd ever do a multiplication in void context, but it is legal.
If your lexer can distinguish type names from other identifiers, the problem is solved, and you can use BNF from there.
If your lexer can distinguish type names from other identifiers, the problem is solved, and you can use BNF from there.