Parsing CSV files

Shawn P. Garbett
Tue, 29 Jul 2003 10:01:37 -0500

I did a small search for parsing a comma seperated file in Haskell and didn't 
find anything-- so I put together some code to do this. It doesn't handle 
whitespace very well, this would be a nice addition if someone has an idea 
out there. Also the rows method, I had trouble just using two do loops 
without brackets, I couldn't prevent it from being ambiguous.

Anyway here's the code:
import Parsec
import System.IO

-- Code to parse a comma seperated file
content   :: Parser String
content    = many1 (noneOf "\"")

cell      :: Parser String
cell       = do char '\"'
                w <- content;
                char '\"' <?> "end of cell"
                return w;
             <|> return "" -- Empty cell

separator :: Parser ()
separator  = skipMany1 (char ',')

cells     :: Parser [String]
cells      = sepBy1 cell separator

contents  :: Parser [String]
contents   = sepBy1 content separator;

rows      :: Parser [[String]]
rows       = do c <- cells
                do { cs <- rows; return (c:cs); } <|> return [c]

csv       :: Parser [[String]]
csv        = do r <- rows
                return r

-- Main routine
main :: IO ()
main  = do result <- parseFromFile csv "simple.txt"
           case (result) of
             Left err  -> print err
             Right sb  -> print sb

Shawn Garbett