module Data.CharMap.Builder where import Data.Map.Static.Builder import Data.List import Data.Ord import Data.Char import Data.Bits import Data.Word data BuildingBlock = SingleMapping Char [Word8] | RangeMapping Char Char Int [(Word8,Word8)] charRange :: BuildingBlock -> (Char,Char) charRange (SingleMapping c _) = (c,c) charRange (RangeMapping s e _ _) = (s,e) mappingLength :: BuildingBlock -> Int mappingLength (SingleMapping _ w) = length w mappingLength (RangeMapping _ _ _ ws) = length ws isRange :: BuildingBlock -> Bool isRange (SingleMapping _ _) = False isRange (RangeMapping _ _ _ _) = True buildCharMap :: [BuildingBlock] -> String buildCharMap lst = let slst = sortBy (comparing (fst.charRange)) lst grps = groupBy (\x y -> (not (isRange x || isRange y)) && mappingLength x == mappingLength y ) slst split' xs = splitAt (length xs `div` 2) xs build' [] _ _ = "DeadEnd" build' [[RangeMapping st end off (x:xs)]] bl br = let e1 = if bl < st then "Node ("++show st++") DeadEnd ("++e2++")" else e2 e2 = if br>end then "Node ("++show end++") ("++e3++") DeadEnd" else e3 e3 = "LeafRange"++show (length xs+1)++" ("++show (ord st - off)++") " ++show (fst x)++concat (map (\(w,r) -> " "++show w++" "++show r) xs) in e1 build' [mps@((SingleMapping _ w):_)] bl br = "LeafMap"++show (length w)++" (" ++(case length w of 1 -> buildStaticMap (map (\(SingleMapping c [w]) -> (c,w)) mps) 2 -> buildStaticMap $ map (\(SingleMapping c [w1,w2]) -> (c,((fromIntegral w1) `shiftL` 8) .|. (fromIntegral w2)::Word16) ) mps 4 -> buildStaticMap $ map (\(SingleMapping c [w1,w2,w3,w4]) -> (c,((fromIntegral w1) `shiftL` 24) .|. ((fromIntegral w2) `shiftL` 16) .|. ((fromIntegral w3) `shiftL` 8) .|. (fromIntegral w4)::Word32) ) mps)++")" build' mps bl br = let (l,r@((spl:_):_)) = split' mps (el,_) = charRange spl in "Node ("++show el++") ("++build' l bl (pred el)++") ("++ build' r el br++")" in build' grps minBound maxBound