packages feed

Tablify-0.8: src/CSV.hs

{-# LANGUAGE RankNTypes #-}

module CSV where
import Text.ParserCombinators.Parsec

-- these CSV file parsing routines courtesy of Real World Haskell:
-- http://book.realworldhaskell.org/read/using-parsec.html

csvFile :: forall st. GenParser Char st [[String]]
csvFile = endBy line eol

line :: forall st. GenParser Char st [String]
line = sepBy cell (char ',')

cell :: forall st. GenParser Char st String
cell = quotedCell <|> many (noneOf ",\n\r")

quotedCell :: forall st. GenParser Char st String
quotedCell = 
    do _ <- char '"'
       content <- many quotedChar
       _ <- char '"' <?> "quote at end of cell"
       return content

quotedChar :: forall st. GenParser Char st Char
quotedChar =
        noneOf "\""
    <|> try (string "\"\"" >> return '"')

eol :: forall st. GenParser Char st String
eol =   try (string "\n\r")
    <|> try (string "\r\n")
    <|> string "\n"
    <|> string "\r"
    <?> "end of line"

parseCSV :: String -> Either ParseError [[String]]
parseCSV = parse csvFile "(unknown)"