{- hspp <in >out
   copies standard input to standard output with the following changes
   happening outside comments and string literals.  It cannot handle a
   Literate Haskell source file, but a similar program could.

   (1) <letter> - <letter> is changed to <letter> _ <letter>,
   (2) <lower> _ <lower> is changed to <lower> <upper>.

   in that order.
   Example of (1)-then-(2):
     echo "let time-of-day = now in time-of-day - total-time" | hspp
 =>  let timeOfDay = now in timeOfDay - totalTime
   Example of (2):
     hspp <hspp.hs
   Note that it is NOT confused by n-1.
-}
import Char
main = getContents >>= putStr . hspp

hspp :: String -> String

hspp ('{':'-':xs) = '{':'-' : hspp_nested_comment 1 xs
hspp ('-':'-':xs) = '-':'-' : hspp_eoline_comment   xs
hspp ('"':xs)     = '"'     : hspp_string '"'  xs
hspp ('\'':xs)    = '\''    : hspp_string '\'' xs
hspp (x:'-':y:xs) | isAlpha x && isAlpha y =     hspp (x:'_':y:xs)
hspp (x:'_':y:xs) | isLower x && isLower y = x : hspp (toUpper y : xs)
hspp (x:xs)       = x       : hspp xs
hspp []           = []

hspp_nested_comment :: Int -> String -> String
 -- Int should be safe provided comments are not nested 2147483648
 -- levels deep.

hspp_nested_comment 0 xs           = hspp xs
hspp_nested_comment n ('{':'-':xs) = '{':'-' : hspp_nested_comment (n+1) xs
hspp_nested_comment n ('-':'}':xs) = '-':'}' : hspp_nested_comment (n-1) xs
hspp_nested_comment n (x:xs)       = x       : hspp_nested_comment  n    xs
hspp_nested_comment n []           = '-':'}' : hspp_nested_comment (n-1) []

hspp_eoline_comment :: String -> String

hspp_eoline_comment ('\n':xs) = '\n' : hspp xs
hspp_eoline_comment (x:xs)    = x    : hspp_eoline_comment xs
hspp_eoline_comment []        = "\n"

hspp_string :: Char -> String -> String

hspp_string q (x:xs) | x == q = x : hspp xs
hspp_string q ('\\':x:xs)     = '\\' : x : hspp_string q xs   
hspp_string q (x:xs)          = x        : hspp_string q xs
hspp_string q []              = [q,'\n']


