module FSH_CSV where import Transform import Text.ParserCombinators.ReadP import Language.Haskell.Interpreter as I import Data.List --- PARSING isChar = (/=',') charParser :: ReadP [Char] charParser = many1 (satisfy isChar) -- This parses characters till a comma is encountered getParsed :: ReadS [Char] getParsed = readP_to_S charParser -- Leading comma needs to be removed or else our parser will output [] removeLeadingComma (',':xs) = removeLeadingComma xs removeLeadingComma str = str -- Only the last element is of interest, rest are incomplete getPair :: [Char] -> ([Char], [Char]) getPair line = parsedPair $ getParsed.removeLeadingComma $ line where parsedPair list@(x:xs) = last list parsedPair [] = ("","") {- - When we run getPair on a string, we get a pair of strings. - The first half is parsed, the second half failed our parser. - The second half failed because it had comma, so if we run getPair on - the unparsed string, it will ultimately be parsed. - - And that is the solution presented here, we run getPair, - pick the parsed part and put it in a list, and run getPair on unparsed part. - We do this till unparsed is [] ie empty and then we return the list of parsed words. -} getWords' :: [[Char]] -> ([Char], [Char]) -> [[Char]] getWords' list (parsed,[]) = list++[parsed] getWords' list (parsed,unparsed) = return (getPair $ unparsed) >>= getWords' (if length parsed > 0 then (list++[parsed]) else []) getWords :: [Char] -> [[Char]] getWords line = getWords' [] ([],line) --- END PARSING --- TRANSFORMING mapLines :: [[Char]] -> [[[Char]]] mapLines = map getWords mapQuotes :: [[String]] -> [[Char]] mapQuotes = map ((\str->","++str).toStringList.encloseWithQuotes) mapBraces :: [String] -> [Char] mapBraces list = "[" ++ (tail (unwords list)) ++ "]" parse :: [[Char]] -> [Char] parse = mapBraces.mapQuotes.mapLines --- END TRANSFORMING --- EXECUTING printList (x:xs) = putStrLn x >> printList xs printList [] = return () run :: [Char] -> String -> IO () run functionStr processedArgs = do splits <- return (lines processedArgs) header <- return (head splits) unparsed <- return (tail splits) result <- runInterpreter $ setImports ["Prelude"] >> interpret (functionStr ++ " " ++ parse unparsed) (as :: [[String]]) case result of (Right res) -> do outputMatrix <- return $ (getWords header) : res output <- return $ map (intercalate ",") outputMatrix printList output (Left err) -> error $ show err --- END EXECUTING