From ed35d03fbdafce4d6d41d8731318304a8eb7ff61 Mon Sep 17 00:00:00 2001 From: Jed Barber Date: Fri, 6 Jan 2017 00:11:00 +1100 Subject: Ballot counting working, but results differ slightly from AEC counts --- src/CSV.hs | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/CSV.hs (limited to 'src/CSV.hs') diff --git a/src/CSV.hs b/src/CSV.hs new file mode 100644 index 0000000..ae2bbea --- /dev/null +++ b/src/CSV.hs @@ -0,0 +1,59 @@ +{-# LANGUAGE FlexibleContexts #-} + +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" + -- cgit