[Fencommits] fenserve: a module for parsing CSV

Benja Fallenstein benja.fallenstein at gmail.com
Sat Jun 9 05:12:14 EEST 2007


Sat Jun  9 05:06:03 EEST 2007  Benja Fallenstein <benja.fallenstein at gmail.com>
  * a module for parsing CSV
diff -rN -u old-fenserve/fendata/CSV.hs new-fenserve/fendata/CSV.hs
--- old-fenserve/fendata/CSV.hs	1970-01-01 02:00:00.000000000 +0200
+++ new-fenserve/fendata/CSV.hs	2007-06-09 05:12:13.000000000 +0300
@@ -0,0 +1,42 @@
+{-# OPTIONS_GHC -fglasgow-exts -fno-monomorphism-restriction #-}
+
+-- A module for parsing CSV.
+
+-- I (Benja) found http://www.xoltar.org/old_site/languages/haskell/CSV.hs,
+-- but it didn't seem to work right and fixing it seemed harder than
+-- to write my own. This module follows the CSV spec at
+-- http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm. I made it so that
+-- it cannot fail (every string parses to *something*); this seems sensible
+-- for our application (data import).
+
+module CSV (parseCSV) where
+
+import Control.Monad.State
+import Data.Char
+
+type Input = String
+
+type CsvField = String
+type CsvLine = [CsvField]
+type CsvFile = [CsvLine]
+
+parseCSV :: Input -> CsvFile
+parseCSV inp = filter (/= [""]) $ reverse $ map reverse $ map (map reverse) $ 
+               execState (normal inp) [[""]] where
+
+normal ('"':cs) = quoted cs
+normal (',':cs) = pushField >> normal cs
+normal ('\r':'\n':cs) = pushLine >> normal cs
+normal ('\n':cs) = pushLine >> normal cs
+normal (c:cs) | isSpace c = normal cs
+              | otherwise = char c >> normal cs
+normal "" = return ()
+
+quoted ('"':'"':cs) = char '"' >> quoted cs
+quoted ('"':cs) = normal cs
+quoted (c:cs) = char c >> quoted cs
+quoted "" = return ()
+
+char c = modify $ \((cs:fields):lines) -> ((c:cs) : fields) : lines
+pushField = modify $ \(fields:lines) -> ("" : fields) : lines
+pushLine = modify $ \lines -> [""] : lines




More information about the Fencommits mailing list