summaryrefslogtreecommitdiff
path: root/src/csv.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/csv.hs')
-rw-r--r--src/csv.hs57
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"
+