Given an ASCII string, decide whether it is a valid C integer literal.
C integer literal
A C integer literal consists of:
0followed by zero or more octal digits (
A nonzero decimal digit followed by zero or more decimal digits (
0x, followed by one or more hexadecimal digits (
optionally followed by one of:
u, which are the "unsigned" suffixes
ll, which are the "long" and "long long" suffixes
Any combination of the above, in any order.
Note that there can be arbitrarily many digits, even though C doesn't support arbitrary-length integers. Likewise, even if the literal with
l and co would overflow the
long type or co, it is still considered a valid literal.
Also note that there must not be a leading plus or minus sign, for it is not considered to be a part of the literal.
It is implementation-defined to accept leading or trailing whitespaces.
Non-ASCII string falls in don't care situation.
19827489765981697847893769837689346573uLL(Digits can be arbitrarily many even if it wouldn't fit the
unsigned long longtype)
0x8f6aa032838467beee3939428l(So can to the
0XCa0(You can mix cases)
0x(A digit must follow
-42(Leading signature isn't a part of the literal)
llis valid for the
42LLLL(Redundant type specifier)
42Uu(Redundant type specifier)
42Ulu(Redundant type specifier)
42lul(Redundant type specifier)
42H(Invalid type specifier)
0b1110010000100100001(Valid C++, but not valid C)
Doesn't recognize leading or trailing whitespaces.
() on success. Monadic failure otherwise.
import Text.ParserCombinators.ReadP decideCIntegerLit :: ReadP () decideCIntegerLit = do choice [ do '0' <- get munch (flip elem "01234567"), do satisfy (flip elem "123456789") munch (flip elem "0123456789"), do '0' <- get satisfy (flip elem "Xx") munch1 (flip elem "0123456789ABCDEFabcdef") ] let unsigned = satisfy (flip elem "Uu") let long = string "l" +++ string "L" +++ string "ll" +++ string "LL" (unsigned >> long >> return ()) +++ (optional long >> optional unsigned) eof