> if (c >= 'a' && c <= 'z')

This relies on ASCII being used, which I think should be mentioned. Somewhat
related, but C2Y is standardizing sequential hex digits so case'a'...'f' and
case'A'...'F' will work regardless of the character set used.

Do you have a link for that?
 
> case 0...9 is not valid because 0. and .9 are parsed as floating-point-literals, with one . between.

0...9 is parsed as one pp-number, rather than three tokens.

Hmm, I was under the impression that the pp-tokens are broken up into one or more tokens, so that's what you would eventually get those three tokens out of it.