-- Turns a raw C string into lines, taking into account lines that are 
-- explicitly broken with a trailing slash (\).

module Language.C.Comments.LineParser (parseLines) where

isWhitespace :: Char -> Bool
isWhitespace ' ' = True
isWhitespace '\t' = True
isWhitespace _ = False

stripTrailingWhitespace :: String -> String
stripTrailingWhitespace = reverse . (dropWhile isWhitespace) . reverse

stripBreak :: String -> String
stripBreak s | isBrokenLine s  = dropLast (stripTrailingWhitespace s)
             | otherwise       = s
  where 
    dropLast = reverse . tail . reverse
  
isBrokenLine :: String -> Bool
isBrokenLine = (endsWith '\\') . stripTrailingWhitespace
  where 
    startsWith _ [] = False
    startsWith x (y:_) = x == y
    endsWith = \c -> (startsWith c) . reverse

joinBrokenLines :: [String] -> [String]
joinBrokenLines [] = []
joinBrokenLines [line] = [stripBreak line] -- if the last line is broken
joinBrokenLines (line1:line2:rest) =
  if isBrokenLine line1 then 
    let joinedLine = (stripBreak line1) ++ line2 in
    joinBrokenLines (joinedLine:rest)
  else 
    line1:(joinBrokenLines (line2:rest))

parseLines :: String -> [String]
parseLines = joinBrokenLines . lines