# 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 (07)

• A nonzero decimal digit followed by zero or more decimal digits (09)

• 0X or 0x, followed by one or more hexadecimal digits (09, AF, and af)

• optionally followed by one of:

• One of U or u, which are the "unsigned" suffixes

• One of L, l, LL, or 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.

# 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 the unsigned long long type)

• 0x8f6aa032838467beee3939428l (So can to the long type)

• 0XCa0 (You can mix cases)

## Falsy

• 08 (Non-octal digit)

• 0x (A digit must follow X or x)

• -42 (Leading signature isn't a part of the literal)

• 42Ll (Only LL or ll is valid for the long 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

Doesn't recognize leading or trailing whitespaces.

Returns () on success. Monadic failure otherwise.

import Text.ParserCombinators.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

• Suggested falsey test cases: 1L1L, 0xabucdlu (or any other test case with an l/L/u somewhere in the middle, making it invalid). – Kevin Cruijssen Oct 14 at 8:33
• Suggested test case for floating point values – AZTECCO Oct 14 at 8:46
• Suggested test-case: 2-1 (starts with a digit and is a valid C constant-expression, but not a bare integer literal). So for example feeding a=2-1; or a[2-1]; to a C compiler wouldn't reject it. (Working on a bash answer that uses cc -c after testing the first digit, trying to let a compiler do the heavy lifting.) – Peter Cordes Oct 14 at 12:56
• Suggested test case: 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. – Lynn Oct 14 at 16:21
• "Any combination of the above", as written, seems to include many of the possibilities you list as invalid examples (Ll for example). Can you clarify what combinations are allowed? – Greg Martin Oct 14 at 16:22

# Retina 0.8.2, 60 59 bytes

i^(0[0-7]*|0x[\da-f]+|[1-9]\d*)(u)?(l)?(?-i:\3?)(?(2)|u?)$ Try it online! Link includes test cases. Edit: Saved 1 byte thanks to @FryAmTheEggMan. Explanation: i  Match case-insensitively. ^(0[0-7]*|0x[\da-f]+|[1-9]\d*)  Start with either octal, hex or decimal. (u)?  Optional unsigned specifier. (l)?  Optional length specifier. (?-i:\3?)  Optionally repeat the length specifier case sensitively. (?(2)|u?)$


If no unsigned specifier yet, then another chance for an optional specifier, before the end of the literal.

• You can use \d in the hex character class, too. – FryAmTheEggman Oct 14 at 0:22

# Perl 5-p, 65 61 bytes

@NahuelFouilleul shaved 4 bytes

$_=/^(0[0-7]*|0x\p{Hex}+|[1-9]\d*)(u?l?l?|l?l?u?)$/i*!/lL|Ll/


Try it online!

• could save 2 bytes using l?l? instead of l{0,2} – Nahuel Fouilleul Oct 14 at 9:24
• 61 bytes – Nahuel Fouilleul Oct 14 at 9:50

# Java 8 / Scala polyglot, 89 79 bytes

s->s.matches("(?!.*(Ll|lL))(?i)(0[0-7]*|[1-9]\\d*|0x[\\da-f]+)(u?l?l?|l?l?u?)")


-10 bytes thanks to @NahuelFouilleul

Try it online in Java 8.
Try it online in Scala (except with => instead of -> - thanks to @TomerShetah).

Explanation:

s->           // Method with String parameter and boolean return-type
s.matches(  //  Check whether the input-string matches the regex
"(?!.*(Ll|lL))(?i)(0[0-7]*|[1-9]\\d*|0x[\\da-f]+)(u?l?l?|l?l?u?)")


Regex explanation:

In Java, the String#matches method implicitly adds a leading and trailing ^...$ to match the entire string, so the regex is: ^(?!.*(Ll|lL))(?i)(0[0-7]*|[1-9]\d*|0x[\da-f]+)(u?l?l?|l?l?u?)$

 (?!         )     # The string should NOT match:
^   .*             #   Any amount of leading characters
(     )      #   Followed by:
Ll          #    "Ll"
|lL       #    Or "lL"
# (Since the ?! is a negative lookahead, it acts loose from the
#  rest of the regex below)

(?i)              # Using case-insensitivity,
0           #   A 0
[0-7]*     #   Followed by zero or more digits in the range [0,7]
|            #  OR:
[1-9]       #   A digit in the range [1,9]
\d*    #   Followed by zero or more digits
|            #  OR:
0x          #   A "0x"
[     ]+  #   Followed by one or more of:
\d       #    Digits
a-f    #    Or letters in the range ['a','f']
)(            # And with nothing in between,
)$# the string should end with: u? # An optional "u" l?l? # Followed by no, one, or two "l" | # OR: l?l? # No, one, or two "l" u? # Followed by an optional "u"  • 79 bytes – Nahuel Fouilleul Oct 14 at 10:03 • @NahuelFouilleul Ah, smart way to use the case-insensitivity after we've checked the Ll/lL. Didn't even knew that was possible. Thanks! – Kevin Cruijssen Oct 14 at 10:20 • The same work for scala: Try it online! – Tomer Shetah Oct 14 at 10:53 • @TomerShetah Thanks for mentioning. I've added it as a polyglot. :) – Kevin Cruijssen Oct 14 at 11:02 • It's also a Java/Kotlin polyglot, since Kotlin also uses a -> and Scala uses => – user Oct 14 at 12:38 # C# (.NET Core), 197 191 bytes @nwellnhof shaved 6bytes: using c=System.Console;class P{static void Main(){c.WriteLine(System.Text.RegularExpressions.Regex.IsMatch(c.ReadLine(),@"^(?!.*(Ll|lL))(?i)(0[0-7]*|[1-9]\d*|0x[\da-f]+)(u?l?l?|l?l?u?)$"));}}


Original:

using c=System.Console;using System.Text.RegularExpressions;class P{static void Main(){c.WriteLine(Regex.IsMatch(c.ReadLine(),@"^(?!.*(Ll|lL))(?i)(0[0-7]*|[1-9]\d*|0x[\da-f]+)(u?l?l?|l?l?u?)$"));}}  Try it online! • Nice first answer, welcome to the site! – Redwolf Programs Oct 14 at 13:45 • Since Regex is used only once, you can write System.Text.RegularExpressions.Regex and remove the using statement, saving 6 bytes. – nwellnhof Oct 16 at 13:38 • @nwellnhof Thanks for noticing! – skytomo Oct 16 at 23:24 # Python 3, 103 bytes import re;re.compile("^(0[0-7]*|[1-9]\d*|0[xX][\dA-Fa-f]+)([uU](L|l|LL|ll)?|(L|l|LL|ll)[uU]?)?$").match


Try it online!

just a basic regex, probably very suboptimal

returns a match object for truthy and None for falsy; input may not contain surrounding whitespace

-3 bytes thanks to Digital Trauma (on my Retina answer)
-1 byte thanks to FryAmTheEggman (on my Retina answer)
-3 bytes thanks to pxeger

• This is why regexes are so fun. – Dannyu NDos Oct 14 at 0:02
• 103 bytes – pxeger Oct 14 at 19:25
• @pxeger Oh cool, thanks! – HyperNeutrino Oct 14 at 19:55

^(0[0-7]*|[1-9]\d*|0[xX][\dA-Fa-f]+)([uU](L|l|LL|ll)?|(L|l|LL|ll)[uU]?)?$ Try it online! Just the same regex I used. First time using Retina, I'm sure this can be optimized with some Retina golf things! -3 bytes thanks to Digital Trauma -1 byte thanks to FryAmTheEggman • Also never used Retina, but 55 bytes? – caird coinheringaahing Oct 14 at 0:07 • @cairdcoinheringaahing I thought of that; unfortunately, no. but thanks for trying :P – HyperNeutrino Oct 14 at 0:07 # JavaScript (ES6), 77 bytes s=>/^(0x[\da-f]+|0[0-7]*|[1-9]\d*)(u?l?l?|l?l?u?)$/i.test(s)&!/Ll|lL/.test(s)


Try it online!

### How?

The first regex is case-insensitive. The only invalid patterns that cannot be filtered out that way are "Ll" and "lL". So we use a 2nd case-sensitive regex to take care of them.

# Charcoal, 76 bytes

≔⊟Φ³¬⌕↧θ…0xιη≔✂↧θη⁻ＬθＬ⊟Φ⪪”{“↧←；⭆δa”¶⁼ι↧…⮌θＬι¹ζ›∧⁺Ｌζ¬⊖η⬤ζ№Ｅ∨×⁸ηχ⍘λφι∨№θLl№θlL


Try it online! Link is to verbose version of code. Explanation:

≔⊟Φ³¬⌕↧θ…0xιη


Find the length of the longest prefix of 0x in the lowercased input.

≔✂↧θη⁻ＬθＬ⊟Φ⪪”{“↧←；⭆δa”¶⁼ι↧…⮌θＬι¹ζ


Slice off the prefix and also check for a lowercase suffix of ull, ul, llu or lu, and if so then slice that off as well.

›...∨№θLl№θlL


The original input must not contain Ll or lL.

∧⁺Ｌζ¬⊖η


The sliced string must not be empty unless the prefix was 0.

⬤ζ№Ｅ∨×⁸ηχ⍘λφι


Convert the prefix length to 10, 8 or 16 appropriately, then take that many base 62 digits and check that all of the remaining lowercased characters are one of those digits.

# 05AB1E, 6361 62 bytes

„Uuõª„LLæDl«âDí«JéRʒÅ¿}нõ.;Ðć_ilDć'xQiA6£мÐþQë\7ÝKõQë\þQ}sõÊ*


This isn't too easy without regexes.. :/ Can definitely be golfed a bit more, though.

+1 byte as bug-fix for inputs like "u", "l", "LL", etc. (thanks for noticing @Neil)

Explanation:

„Uu                 # Push string "Uu"
õª               # Convert it to a list of characters, and append an empty string:
#  ["U","u",""]
„LL            # Push string "LL"
æ           # Take its powerset: ["","L","L","LL"]
Dl         # Create a lowercase copy: ["","l","l","ll"]
«        # Merge the lists together: ["","L","L","LL","","l","l","ll"]
â       # Create all possible pairs of these two lists
Dí     # Create a copy with each pair reversed
«    # Merge the list of pairs together
J   # Join each pair together to a single string
éR # Sort it by length in descending order


We now have the list:

["llu","LLu","llU","LLU","ull","uLL","Ull","ULL","ll","LL","lu","lu","Lu","Lu","lU","lU","LU","LU","ll","LL","ul","ul","uL","uL","Ul","Ul","UL","UL","l","l","L","L","u","u","U","U","l","l","L","L","u","u","U","U","","","",""]

ʒ                   # Filter this list by:
Å¿                 #  Where the (implicit) input ends with this string
}н                  # After the filter: only leave the first (longest) one
õ.;               # And remove the first occurrence of this in the (implicit) input
ÐD                  # Triplicate + duplicate (so there are 4 copies on the stack now)
ć                 # Extract head; pop and push remainder-string and first character
# separated to the stack
_i               # If this first character is a 0:
l              #  Convert the remainder-string to lowercase
D             #  Duplicate it †¹
'xQi       '#  If it's equal to "x":
A       #   Push the lowercase alphabet
6£     #   Only leave the first 6 characters: "abcdef"
м    #   Remove all those characters from the string
Ð   #   Triplicate it †²
þ  #   Only keep all digits in the copy
Q #   And check that the two are still the same
#   (thus it's a non-negative integer without decimal .0s)
ë         #  Else:
7Ý      #   Push list [0,1,2,3,4,5,6,7]
K     #   Remove all those digits
õQ   #   Check what remains is an empty string
ë                # Else:
þ              #  Only keep all digits
Q             #  And check that the two are still the same
#  (thus it's a non-negative integer without decimal .0s)
}s               # After the if-else: Swap the two values on the stack
# (this will get the remaining copy of †² for "0x" cases,
#  or the remaining copy of †¹ for other cases)
õÊ             # Check that this is NOT an empty string
*            # And check that both are truthy
# (after which the result is output implicitly)

• This incorrectly outputs 1 for u... – Neil Oct 14 at 14:15
• @Neil Thanks for noticing. Fixed at the cost of 1 byte. – Kevin Cruijssen Oct 14 at 14:21

{print/^(0[0-7]*|[1-9][0-9]*|0[xX][0-9A-Fa-f]+)([uU](L|l|LL|ll)?|(L|l|LL|ll)[uU]?)?$/}  Try it online! Simply prints truthy or falsey depending on whether or not the input line matches the regex. Doesn't accept leading or trailing whitespaces. # Haskell, 169 bytes import Data.Char s!p=s>""&&dropWhile p selemdo u<-["","u","U"];l<-"":words"L l LL ll";[u++l,l++u] f('0':x:s)|elem x"xX"=s!isHexDigit|1<2=(x:s)!isOctDigit f s=s!isDigit  Try it online! # Ruby, 67 bytes ->s{/^(0[0-7]*|[1-9]\d*|0x[\da-f]+)(u?l?l?|l?l?u?)?$/i=~s&&/Ll/!~s}


Try it online!

• Fails for 0lL, no? – Neil Oct 21 at 13:58
• @Neil uhh no? 0lL is invalid (right?), and this returns false for that. – pxeger Oct 21 at 18:14
• When I Try it online! it outputs true... – Neil Oct 21 at 20:26

# Elixir, 74 bytes

&(&1=~~r/^(0[0-7]*|[1-9]\d*|0x[\da-f]+)(u?l?l?|l?l?u?)?\$/i&&!(&1=~~r/Ll/))


Try it online!