{-# LANGUAGE OverloadedStrings #-} module CSV.Parse ( parse ) where import qualified Data.Attoparsec.Text as A import qualified Data.Text as Text import Control.Applicative import CSV.Types -- | 'parse' parses text in the CSV format. Delimiters are ',' and new lines. -- Quotation is performed with '"'. -- TODO: Files in the wrong format throw an error :( parse :: Text.Text -> CSV SQLVal parse text = case A.parseOnly csvParser text of Left s -> error s Right c -> c csvParser :: A.Parser (CSV SQLVal) csvParser = do rows <- A.sepBy1 rowParser (A.skip A.isEndOfLine) return (CSV rows) rowParser :: A.Parser [SQLVal] rowParser = A.sepBy1 elementParser $ A.string ", " elementParser :: A.Parser SQLVal elementParser = I <$> A.decimal <|> do text <- A.many1 $ textParser <|> quotationParser return (NVar $ Text.concat text) textParser :: A.Parser Text.Text textParser = A.takeWhile1 (A.notInClass [',','\n', '"']) quotationParser :: A.Parser Text.Text quotationParser = let quote = '"' in let f q1 t q2 = Text.cons q1 (Text.snoc t q2) in f <$> A.char quote <*> quotedString [quote] <*> A.char quote quotedString :: String -> A.Parser Text.Text quotedString quote = A.takeWhile (A.notInClass quote)