diff options
author | Jed Barber <jjbarber@y7mail.com> | 2017-01-03 23:38:20 +1100 |
---|---|---|
committer | Jed Barber <jjbarber@y7mail.com> | 2017-01-03 23:38:20 +1100 |
commit | a13d9db820d7cb83e9472e2cf387eb22c26d402d (patch) | |
tree | d9c8ccdc299a00867ee8104c94097aba9234273b /src/csv.hs |
Initial commit
Diffstat (limited to 'src/csv.hs')
-rw-r--r-- | src/csv.hs | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/csv.hs b/src/csv.hs new file mode 100644 index 0000000..ddef1d2 --- /dev/null +++ b/src/csv.hs @@ -0,0 +1,57 @@ +module CSV( + Settings(..), + specialChars, + defaultSettings, + parseRecord + ) where + + + + +import Text.ParserCombinators.Parsec +import Data.Char + + + + +data Settings = Settings { separator :: Char + , quote :: Char + , escape :: Char } + + +specialChars :: Settings -> String +specialChars s = (separator s):(quote s):(escape s):[] + + +defaultSettings = Settings { separator = ',', quote = '\"', escape = '\\' } + + + + +parseRecord :: Settings -> String -> Either ParseError [String] +parseRecord settings input = + parse (record settings) "error" input + + + + +record s = do + f <- (field s) `sepBy` (char (separator s)) + optional eol + eof + return f + + +field s = many (try (quoted s) <|> many1 (fieldChar s)) >>= return . foldl1 (++) +quoted s = between (char (quote s)) (char (quote s)) (many (quotedChar s)) +fieldChar s = allExcept s (specialChars s) +quotedChar s = allExcept s [quote s] +allExcept s c = try (escapeChar s) <|> satisfy (\x -> (not (isControl x)) && (x `notElem` c)) +escapeChar s = char (escape s) >> oneOf (specialChars s) + + +eol = try (string "\r\n") + <|> try (string "\r") + <|> try (string "\n") + <?> "end of line" + |