import Data.Char
import System.Environment

-- for category names, see http://haskell.org/ghc/docs/7.0-latest/html/libraries/base-4.3.0.0/Data-Char.html#3
isValid c = (generalCategory c) `elem`
    [UppercaseLetter, LowercaseLetter, TitlecaseLetter, ModifierLetter,
     OtherLetter, LetterNumber, DecimalNumber, NonSpacingMark,
     SpacingCombiningMark, ConnectorPunctuation]

main = putStrLn regex

regex = stringify $ combine ranges

data Range = Range Char Char

lower (Range a b) = a
upper (Range a b) = b

combine [] = []
combine [a] = [a]
combine (a:b:rest)
    | lower b == succ (upper a) = combine (Range (lower a) (upper b) : rest)
combine (a:rest) = (a : combine rest)

stringify = concat . map str

str (Range a b) | a == b    = esc a
                | succ a == b = esc a ++ esc b
                | otherwise = esc a ++ "-" ++ esc b

esc c = "\\\\u" ++ hex (ord c) 4

hex n 0 = ""
hex n m = hex (n `div` 16) (m - 1) ++ [intToDigit $ n `mod` 16]

ranges = map toRange $ filter isValid ['\0'..'\xffff']

toRange c = Range c c

