There is an ambiguity. When parsing "0xE+1" there's an ambiguity as to whether the "E" belongs to a 'hex digit**' as part of a 'hex constant' or to an 'exponent'.
I don't agree. There is no ambiguity IMO if you stick to what the standard defines.
As I said, I hadn't [at the time] divined whether this is standard or compiler implementation and left the 'blame' open, but it's now clear that it's the compiler(s) in question. The cause is almost certainly using an "ambiguous grammar*", and an incorrect one to boot. It's pretty clear, just from the context of the error, that there is in the compiler's implementation of it's own grammar for the language an ambiguity between recognising an expression with a hex constant on the left and recognising a constant with an exponent part when a hex E immediately precedes the operator.
Oh, if you meant an ambiguity in the grammar the compiler actually uses, then obviously I agree.
I thought you meant this was ambiguous from the standard itself, which I don't agree with... with a "but". I still have to admit that the C grammar, as exposed in the C standard(s) (this hasn't really improved much), is not that clearly defined. I wish they would add some kind of clear BNF, or something in that vein. There isn't, and (at least IMHO) I think the grammar is exposed pretty "loosely" in the standard itself. That should be addressed in future revisions IMO.
That said, I still see the way this compiler implements parsing (thanks for finding the "offending" part in the source code!) a bit questionable. The C grammar is *heavily* context-dependent (which makes parsing it correctly not really a fun experience), and in this example, I do think they don't use the context properly. Parsing the token(s) possibly representing an exponent part independently of the context (which is a hex constant, due to the prefix) is, IMO, a parsing error. Now to be fair, I admit the parser still has to make a choice regarding the context. When it encounters "0xE+1", did the programmer actually mean "0xE + 1", or was the "0x" actually not intended, and the programmer meant a decimal floating constant instead? Or maybe they meant a hex floating constant, but used "E" instead of "P"? My take on approaching this kind of stuff when writing a parser is pretty simple: 1/ use common sense, 2/ parse it as the "most likely" (here, if "0xE" was written, the probability of meaning anything else than a hex constant is pretty low, unless you want your parser to outsmart people using it, which never works) and finally 3/ determine the context. Finally, the parser should try its best *not* to trigger an *error* if the written code has any possibility of being actually correct. If it encounters something that may look like a typical possible mistake, it should then issue a warning, but not throw an error. Such as when GCC encounters "if (x = y)", it will throw a warning, because this is a common source of bug. This is nice.
But I know this is definitely not easy. C is a bitch to parse, because not only is it heavily context-dependent, but the context is sometimes determined starting from the right first, and sometimes starting from the left (due to the "reversed" nature of many C constructs, such as declarations.) Wirthian languages (Pascal, Modula, Oberon, Ada and many more derivatives) are definitely much, much nicer to parse.