Objective
Given an ASCII string, decide whether it is a valid C integer literal.
C integer literal
A C integer literal consists of:
One of:
0
followed by zero or more octal digits (0
–7
)A nonzero decimal digit followed by zero or more decimal digits (
0
–9
)0X
or0x
, followed by one or more hexadecimal digits (0
–9
,A
–F
, anda
–f
)
optionally followed by one of:
One of
U
oru
, which are the "unsigned" suffixesOne of
L
,l
,LL
, orll
, which are the "long" and "long long" suffixesAny 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.
Rules
It is implementation-defined to accept leading or trailing whitespaces.
Non-ASCII string falls in don't care situation.
Examples
Truthy
0
007
42u
42lu
42UL
19827489765981697847893769837689346573uLL
(Digits can be arbitrarily many even if it wouldn't fit theunsigned long long
type)0x8f6aa032838467beee3939428l
(So can to thelong
type)0XCa0
(You can mix cases)
Falsy
08
(Non-octal digit)0x
(A digit must followX
orx
)-42
(Leading signature isn't a part of the literal)42Ll
(OnlyLL
orll
is valid for thelong long
type)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)Hello
Empty string
Ungolfed solution
Haskell
Doesn't recognize leading or trailing whitespaces.
Returns ()
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
1L1L
,0xabucdlu
(or any other test case with anl
/L
/u
somewhere in the middle, making it invalid). \$\endgroup\$2-1
(starts with a digit and is a valid C constant-expression, but not a bare integer literal). So for example feedinga=2-1;
ora[2-1];
to a C compiler wouldn't reject it. (Working on abash
answer that usescc -c
after testing the first digit, trying to let a compiler do the heavy lifting.) \$\endgroup\$0o765
. This is a valid octal literal in many languages that might try to get away with a built-in "eval" / "read-int" sort of approach, but it's not valid C. \$\endgroup\$Ll
for example). Can you clarify what combinations are allowed? \$\endgroup\$